Package com.tll.client.model

Source Code of com.tll.client.model.ModelChangeTracker

/**
* The Logic Lab
* @author jpk
* @since Sep 22, 2009
*/
package com.tll.client.model;

import java.util.HashSet;

import com.tll.common.bind.IPropertyChangeListener;
import com.tll.common.bind.PropertyChangeEvent;
import com.tll.common.model.CopyCriteria;
import com.tll.common.model.IModelProperty;
import com.tll.common.model.IPropertyValue;
import com.tll.common.model.Model;
import com.tll.common.model.PropertyPathException;
import com.tll.model.schema.PropertyMetadata;

/**
* ModelChangeTracker - Tracks model properties whose value has changed (become
* dirty).
* @author jpk
*/
public final class ModelChangeTracker implements IPropertyChangeListener {

  /**
   * The set of model properties marked as changed.
   */
  private HashSet<IModelProperty> propRefChanges;

  /**
   * Set of property paths marked as changed.
   */
  private HashSet<String> pathChanges;

  /**
   * Flag to turn on/off this tracker to jive with the field binding life-cycle.
   */
  private boolean handleChanges = true;

  /**
   * Manually add a change by model property ref
   * @param mp the model property ref
   */
  public void addChange(IModelProperty mp) {
    if(mp instanceof IPropertyValue) {
      final PropertyMetadata pm = ((IPropertyValue)mp).getMetadata();
      if(pm != null && pm.isManaged()) return// don't track managed props
    }
    if(propRefChanges == null) {
      propRefChanges = new HashSet<IModelProperty>();
    }
    propRefChanges.add(mp);
  }

  /**
   * Manuall add a change by a root relative property path
   * @param path relative to the root model subject to editing
   */
  public void addChange(String path) {
    if(pathChanges == null) {
      pathChanges = new HashSet<String>();
    }
    pathChanges.add(path);
  }

  /**
   * Removes a previously added model prop ref change.
   * @param mp the prop ref to remove
   */
  public void removeChange(IModelProperty mp) {
    if(propRefChanges != null) {
      propRefChanges.remove(mp);
    }
  }

  /**
   * Removes a previously added path change.
   * @param path the path to remove
   */
  public void removeChange(String path) {
    if(pathChanges != null) {
      pathChanges.remove(path);
    }
  }

  @Override
  public void propertyChange(PropertyChangeEvent evt) {
    if(!handleChanges) return;
    final Object src = evt.getSource();
    if(src instanceof Model) {
      try {
        final IModelProperty mp = ((Model) src).getModelProperty(evt.getPropertyName());
        addChange(mp);
      }
      catch(final PropertyPathException e) {
        throw new IllegalStateException("Unable to resolve model property: " + evt.getPropertyName()
            + " due to error: " + e.getMessage(), e);
      }
    }
    else if(src instanceof IModelProperty) {
      addChange((IModelProperty) src);
    }
    else {
      throw new IllegalArgumentException("Unhandled event source type: " + src);
    }
  }

  /**
   * @return <code>true</code> if this instance is tracking changes.
   */
  public boolean isHandleChanges() {
    return handleChanges;
  }

  /**
   * Manually turns or or off property change tracking.
   * @param handleChanges the handleChanges to set
   */
  public void setHandleChanges(boolean handleChanges) {
    this.handleChanges = handleChanges;
  }

  /**
   * @return The total number of recorded changes.
   */
  public int getNumChanges() {
    int c = 0;
    if(propRefChanges != null) c+= propRefChanges.size();
    if(pathChanges != null) c+= pathChanges.size();
    return c;
  }

  /**
   * Removes all changes.
   */
  public void clear() {
    if(propRefChanges != null) propRefChanges.clear();
    if(pathChanges != null) pathChanges.clear();
  }

  /**
   * Generates a new {@link Model} instance containing a sub-set of the given
   * model containing only those properties that were altered.
   * @param root The root model
   * @return {@link Model} instance containing only those properties that were
   *         previously added to this tracker or <code>null</code> if no changes
   *         were added.
   */
  public Model generateChangeModel(Model root) {
    if(propRefChanges == null && pathChanges == null) return null;
    final HashSet<IModelProperty> allChanges = new HashSet<IModelProperty>();
    if(propRefChanges != null) {
      allChanges.addAll(propRefChanges);
    }
    if(pathChanges != null) {
      for(final String path : pathChanges) {
        IModelProperty mp;
        try {
          mp = root.getModelProperty(path);
        }
        catch(final PropertyPathException e) {
          throw new IllegalStateException("Unable to resolve path: " + path, e);
        }
        allChanges.add(mp);
      }
    }
    return root.copy(CopyCriteria.changes(allChanges));
  }
}
TOP

Related Classes of com.tll.client.model.ModelChangeTracker

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.