Package com.tll.common.model

Source Code of com.tll.common.model.RelatedManyProperty

/**
* The Logic Lab
*/
package com.tll.common.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import com.tll.common.bind.PropertyChangeEvent;
import com.tll.model.schema.PropertyType;
import com.tll.util.PropertyPath;

/**
* RelatedManyProperty
* @author jpk
*/
public final class RelatedManyProperty extends AbstractRelationalProperty implements Iterable<IndexedProperty> {

  /**
   * The list of indexed props.
   */
  private ArrayList<IndexedProperty> list = new ArrayList<IndexedProperty>();

  /**
   * The value collection whereby each indexed model corresponds to the wrapped
   * model in the {@link #list}.
   */
  private ArrayList<Model> mlist;

  /**
   * Constructor
   */
  public RelatedManyProperty() {
    super();
  }

  /**
   * Constructor
   * @param manyType The required related many Model type.
   * @param propName
   * @param reference
   * @param clc Collection of {@link Model}s.
   */
  public RelatedManyProperty(final IEntityType manyType, final String propName, final boolean reference,
      final Collection<Model> clc) {
    super(manyType, propName, reference);
    setValue(clc);
  }

  public PropertyType getType() {
    return PropertyType.RELATED_MANY;
  }

  public Object getValue() {
    return getModelList();
  }

  @SuppressWarnings("unchecked")
  public void setValue(Object value) throws IllegalArgumentException {
    if(this.mlist == value) return;

    if(value == null) {
      if(mlist != null) {
        final Object old = mlist;
        list.clear();
        mlist = null;
        getChangeSupport().firePropertyChange(propertyName, old, mlist);
      }
    }
    else if(value instanceof Collection) {
      final Collection<Model> clc = (Collection) value;
      final Object old = mlist;
      list.clear();
      if(mlist == null) {
        mlist = new ArrayList<Model>(clc.size());
      }
      else {
        mlist.clear();
      }
      int i = 0;
      for(final Model im : clc) {
        final IndexedProperty ip = new IndexedProperty(relatedType, im, propertyName, isReference(), i++);
        list.add(ip);
        mlist.add(im);
      }
      // IMPT: refer to the value agrument as the new value to avoid spurious
      // re-firings of property change events
      getChangeSupport().firePropertyChange(propertyName, old, value);
    }
    else {
      throw new IllegalArgumentException("The value must be a collection of Model instances");
    }

  }

  /**
   * Provides the encased List of {@link Model}s.
   * <p>
   * <em><b>IMPT:</b>Mutations made to this list do <b>NOT</b> invoke {@link PropertyChangeEvent}s.</em>
   * @return the list of indexed models
   */
  public List<Model> getModelList() {
    return mlist;
  }

  /**
   * Get an indexed property at the given index.
   * @param index The index
   * @throws IndexOutOfBoundsException
   * @return The {@link IndexedProperty} at the given index.
   */
  public IndexedProperty getIndexedProperty(int index) throws IndexOutOfBoundsException {
    return list.get(index);
  }

  public Iterator<IndexedProperty> iterator() {
    return list.iterator();
  }

  @Override
  public void setProperty(String propPath, Object value) throws PropertyPathException, IllegalArgumentException {
    final PropertyPath pp = new PropertyPath(propPath);
    if(pp.isIndexed()) {
      if(value != null && value instanceof Model == false) {
        throw new IllegalArgumentException("The value must be a Model instance");
      }

      final Model m = (Model) value;
      Model old = null;

      final int index;
      try {
        index = pp.index();
      }
      catch(final IllegalArgumentException e) {
        throw new MalformedPropPathException(e.getMessage());
      }
      final int size = size();

      if(index == size) {
        // we're appending a new index
        if(m != null) {
          // add
          if(mlist == null) {
            mlist = new ArrayList<Model>();
          }
          mlist.add(m);
          list.add(new IndexedProperty(relatedType, m, propertyName, isReference(), index));
        }
      }
      else if(index < size) {
        if(m != null) {
          // replace
          old = mlist.set(index, m);
          list.get(index).setModel(m, false);
        }
        else {
          // remove
          old = mlist.remove(index);
          list.remove(index);
        }
      }
      else {
        throw new IndexOutOfRangeInPropPathException(propPath, pp.last(), pp.index());
      }
      if(old != value) {
        getChangeSupport().fireIndexedPropertyChange(propertyName, index, old, value);
      }
    }
    else {
      setValue(value);
    }

    assert ((mlist == null && list.size() == 0) || (mlist.size() == list.size()));
  }

  /**
   * @return The number of indexed models in this related many list.
   */
  public int size() {
    return list == null ? 0 : list.size();
  }

  @Override
  public String toString() {
    final StringBuilder sb = new StringBuilder();
    sb.append(propertyName);
    sb.append(isReference() ? "[REF] " : " ");
    sb.append(" [");
    if(list != null) {
      for(final Iterator<IndexedProperty> itr = list.iterator(); itr.hasNext();) {
        final IndexedProperty ip = itr.next();
        sb.append(ip);
        if(itr.hasNext()) {
          sb.append(", ");
        }
      }
    }
    sb.append(']');

    return sb.toString();
  }
}
TOP

Related Classes of com.tll.common.model.RelatedManyProperty

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.