001package io.ebeaninternal.server.deploy;
002
003import io.ebean.Query;
004import io.ebean.Transaction;
005import io.ebean.bean.BeanCollection;
006import io.ebean.bean.BeanCollectionAdd;
007import io.ebean.bean.EntityBean;
008import io.ebean.common.BeanSet;
009import io.ebeaninternal.api.SpiEbeanServer;
010import io.ebeaninternal.api.json.SpiJsonWriter;
011
012import java.io.IOException;
013import java.util.LinkedHashSet;
014import java.util.Set;
015
016/**
017 * Helper specifically for dealing with Sets.
018 */
019public class BeanSetHelp<T> extends BaseCollectionHelp<T> {
020
021  /**
022   * When attached to a specific many property.
023   */
024  BeanSetHelp(BeanPropertyAssocMany<T> many) {
025    super(many);
026  }
027
028  /**
029   * For a query that returns a set.
030   */
031  BeanSetHelp() {
032    super();
033  }
034
035  @Override
036  public BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
037    if (bc instanceof BeanSet<?>) {
038      BeanSet<?> beanSet = (BeanSet<?>) bc;
039      if (beanSet.getActualSet() == null) {
040        beanSet.setActualSet(new LinkedHashSet<>());
041      }
042      return beanSet;
043
044    } else {
045      throw new RuntimeException("Unhandled type " + bc);
046    }
047  }
048
049  @Override
050  public BeanCollection<T> createEmptyNoParent() {
051    return new BeanSet<>();
052  }
053
054  @Override
055  public BeanCollection<T> createEmpty(EntityBean ownerBean) {
056    BeanSet<T> beanSet = new BeanSet<>(loader, ownerBean, propertyName);
057    if (many != null) {
058      beanSet.setModifyListening(many.getModifyListenMode());
059    }
060    return beanSet;
061  }
062
063  @Override
064  public BeanCollection<T> createReference(EntityBean parentBean) {
065
066    BeanSet<T> beanSet = new BeanSet<>(loader, parentBean, propertyName);
067    beanSet.setModifyListening(many.getModifyListenMode());
068    return beanSet;
069  }
070
071  @Override
072  public void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
073
074    BeanSet<?> newBeanSet = (BeanSet<?>) server.findSet(query, t);
075    refresh(newBeanSet, parentBean);
076  }
077
078  @Override
079  public void refresh(BeanCollection<?> bc, EntityBean parentBean) {
080
081    BeanSet<?> newBeanSet = (BeanSet<?>) bc;
082
083    Set<?> current = (Set<?>) many.getValue(parentBean);
084
085    newBeanSet.setModifyListening(many.getModifyListenMode());
086    if (current == null) {
087      // the currentList is null?  Not really expecting this...
088      many.setValue(parentBean, newBeanSet);
089
090    } else if (current instanceof BeanSet<?>) {
091      // normally this case, replace just the underlying list
092      BeanSet<?> currentBeanSet = (BeanSet<?>) current;
093      currentBeanSet.setActualSet(newBeanSet.getActualSet());
094      currentBeanSet.setModifyListening(many.getModifyListenMode());
095
096    } else {
097      // replace the entire set
098      many.setValue(parentBean, newBeanSet);
099    }
100  }
101
102  @Override
103  public void jsonWrite(SpiJsonWriter ctx, String name, Object collection, boolean explicitInclude) throws IOException {
104
105    Set<?> set;
106    if (collection instanceof BeanCollection<?>) {
107      BeanSet<?> bc = (BeanSet<?>) collection;
108      if (!bc.isPopulated()) {
109        if (explicitInclude) {
110          // invoke lazy loading as collection
111          // is explicitly included in the output
112          bc.size();
113        } else {
114          return;
115        }
116      }
117      set = bc.getActualSet();
118    } else {
119      set = (Set<?>) collection;
120    }
121    jsonWriteCollection(ctx, name, set);
122  }
123}