/*******************************************************************************
 * Copyright (c) 2007, 2010 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0, which accompanies this distribution
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 * 
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.utility.internal.node;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.Vector;

import org.eclipse.jpt.utility.internal.iterators.CloneIterator;
import org.eclipse.jpt.utility.internal.iterators.CloneListIterator;
import org.eclipse.jpt.utility.internal.iterators.FilteringIterator;
import org.eclipse.jpt.utility.internal.model.AbstractModel;
import org.eclipse.jpt.utility.internal.model.AspectChangeSupport;
import org.eclipse.jpt.utility.internal.model.ChangeSupport;

/**
 * Base class for Node classes.
 * Provides support for the following:
 *     initialization
 *     enforced object identity wrt #equals()/#hashCode()
 *     containment hierarchy (parent/child)
 *     user comment
 *     dirty flag
 *     problems
 *     sorting
 * 
 * Typically, subclasses should consider implementing the following methods:
 *     the appropriate constructors
 *         (with the appropriately-restrictive type declaration for parent)
 *     #initialize()
 *     #initialize(Node parentNode)
 *     #checkParent(Node parentNode)
 *     #addChildrenTo(List list)
 *     #nodeRemoved(Node)
 *     #validator()
 *     #transientAspectNames() or
 *         #addTransientAspectNamesTo(Set transientAspectNames)
 *     #addProblemsTo(List currentProblems)
 *     #nonValidatedAspectNames()
 *         #addNonValidatedAspectNamesTo(Set nonValidatedAspectNames)
 *     #displayString()
 *     #toString(StringBuilder sb)
 */
public abstract class AbstractNode 
	extends AbstractModel
	implements Node
{

	/** Containment hierarchy. */
	private Node parent;  // pseudo-final

	/** Track whether the node has changed. */
	private volatile boolean dirty;
	private volatile boolean dirtyBranch;

	/**
	 * The node's problems, as calculated during validation.
	 * This list should only be modified via a ProblemSynchronizer,
	 * allowing for asynchronous modification from another thread.
	 */
	private Vector<Problem> problems;		// pseudo-final
		private static final Object[] EMPTY_PROBLEM_MESSAGE_ARGUMENTS = new Object[0];

	/**
	 * Cache the node's "branch" problems, as calculated during validation.
	 * This list should only be modified via a ProblemSynchronizer,
	 * allowing for asynchronous modification from another thread.
	 * This must be recalculated every time this node or one of its
	 * descendants changes it problems.
	 */
	private Vector<Problem> branchProblems;		// pseudo-final

	/** User comment. */
	private volatile String comment;


	// ********** static fields **********

	/**
	 * Sets of transient aspect names, keyed by class.
	 * This is built up lazily, as the objects are modified.
	 */
	private static final HashMap<Class<? extends AbstractNode>, HashSet<String>> transientAspectNameSets = new HashMap<Class<? extends AbstractNode>, HashSet<String>>();

	/**
	 * Sets of non-validated aspect names, keyed by class.
	 * This is built up lazily, as the objects are modified.
	 */
	private static final HashMap<Class<? extends AbstractNode>, HashSet<String>> nonValidatedAspectNameSets = new HashMap<Class<? extends AbstractNode>, HashSet<String>>();


	// ********** constructors **********

	/**
	 * Most objects must have a parent.
	 * Use this constructor to create a new node.
	 * @see #initialize(Node)
	 */
	protected AbstractNode(Node parent) {
		super();
		this.initialize();
		this.initialize(parent);
	}


	// ********** initialization **********

	/**
	 * Initialize a newly-created instance.
	 * @see #initialize(Node)
	 */
	protected void initialize() {
		this.comment = ""; //$NON-NLS-1$

		// a new object is dirty, by definition
		this.dirty = true;
		this.dirtyBranch = true;

		this.problems = new Vector<Problem>();
		this.branchProblems = new Vector<Problem>();

	// when you override this method, don't forget to include:
	//	super.initialize();
	}

	/**
	 * Initialize a newly-created instance.
	 * @see #initialize()
	 */
	protected void initialize(Node parentNode) {
		this.checkParent(parentNode);
		this.parent = parentNode;
	// when you override this method, don't forget to include:
	//	super.initialize(parentNode);
	}

	@Override
	protected ChangeSupport buildChangeSupport() {
		return new AspectChangeSupport(this, this.buildChangeSupportListener());
	}

	protected AspectChangeSupport.Listener buildChangeSupportListener() {
		return new AspectChangeSupport.Listener() {
			public void aspectChanged(String aspectName) {
				AbstractNode.this.aspectChanged(aspectName);
			}
		};
	}


	// ********** equality **********

	/**
	 * Enforce object identity - do not allow objects to be equal unless
	 * they are the same object.
	 * Do NOT override this method - we rely on object identity extensively.
	 */
	@Override
	public final boolean equals(Object o) {
		return this == o;
	}

	/**
	 * Enforce object identity - do not allow objects to be equal unless
	 * they are the same object.
	 * Do NOT override this method - we rely on object identity extensively.
	 */
	@Override
	public final int hashCode() {
		return super.hashCode();
	}


	// ********** containment hierarchy (parent/children) **********

	/**
	 * INTRA-TREE API?
	 * Return the node's parent in the containment hierarchy.
	 * Most nodes must have a parent.
	 * @see #children()
	 */
	public Node getParent() {
		return this.parent;
	}

	/**
	 * Throw an IllegalArgumentException if the parent is not valid
	 * for the node.
	 * By default require a non-null parent. Override if other restrictions exist
	 * or the parent should be null.
	 * NB: Root node model implementations will need to override this method.
	 */
	protected void checkParent(Node parentNode) {
		if (parentNode == null) {
			throw new IllegalArgumentException("The parent node cannot be null"); //$NON-NLS-1$
		}
	}

	/**
	 * INTRA-TREE API?
	 * Return the node's children, which are also nodes.
	 * Do NOT override this method.
	 * Override #addChildrenTo(List).
	 * @see #getParent()
	 * @see #addChildrenTo(java.util.List)
	 */
	public final Iterator<Node> children() {
		List<Node> children = new ArrayList<Node>();
		this.addChildrenTo(children);
		return children.iterator();
	}

	/**
	 * Subclasses should override this method to add their children
	 * to the specified list.
	 * @see #children()
	 */
	protected void addChildrenTo(@SuppressWarnings("unused") List<Node> list) {
		// this class has no children, subclasses will...
	// when you override this method, don't forget to include:
	//	super.addChildrenTo(list);
	}

	/**
	 * INTRA-TREE API?
	 * Return the containment hierarchy's root node.
	 * Most nodes must have a root.
	 * @see #getParent()
	 * NB: Assume the root has no parent.
	 */
	public Node root() {
		Node p = this.parent;
		return (p == null) ? this : p.root();
	}

	/**
	 * Return whether the node is a descendant of the specified node.
	 * By definition, a node is a descendant of itself.
	 */
	public boolean isDescendantOf(Node node) {
		return (this == node) || this.parentIsDescendantOf(node);
	}

	protected boolean parentIsDescendantOf(Node node) {
		return (this.parent != null) && this.parent.isDescendantOf(node);
	}

	/**
	 * Return a collection holding all the node's "references", and all
	 * the node's descendants' "references". "References" are
	 * objects that are "referenced" by another object, as opposed
	 * to "owned" by another object.
	 */
	public Iterator<Node.Reference> branchReferences() {
		Collection<Node.Reference> branchReferences = new ArrayList<Node.Reference>(1000);		// start big
		this.addBranchReferencesTo(branchReferences);
		return branchReferences.iterator();
	}

	/**
	 * INTRA-TREE API
	 * Add the node's "references", and all the node's descendants'
	 * "references", to the specified collection. "References" are
	 * objects that are "referenced" by another object, as opposed
	 * to "owned" by another object.
	 * This method is of particular concern to Handles, since most
	 * (hopefully all) "references" are held by Handles.
	 * @see Reference
	 * @see #children()
	 */
	public void addBranchReferencesTo(Collection<Node.Reference> branchReferences) {
		for (Iterator<Node> stream = this.children(); stream.hasNext(); ) {
			Node child = stream.next();		// pull out the child to ease debugging
			child.addBranchReferencesTo(branchReferences);
		}
	}

	/**
	 * Return all the nodes in the object's branch of the tree,
	 * including the node itself. The nodes will probably returned
	 * in "depth-first" order.
	 * Only really used for testing and debugging.
	 */
	public Iterator<Node> allNodes() {
		Collection<Node> nodes = new ArrayList<Node>(1000);		// start big
		this.addAllNodesTo(nodes);
		return nodes.iterator();
	}

	/**
	 * INTRA-TREE API?
	 * Add all the nodes in the object's branch of the tree,
	 * including the node itself, to the specified collection.
	 * Only really used for testing and debugging.
	 */
	public void addAllNodesTo(Collection<Node> nodes) {
		nodes.add(this);
		for (Iterator<Node> stream = this.children(); stream.hasNext(); ) {
			Node child = stream.next();		// pull out the child to ease debugging
			child.addAllNodesTo(nodes);
		}
	}


	// ********** model synchronization support **********

	/**
	 * INTRA-TREE API
	 * This is a general notification that the specified node has been
	 * removed from the tree. The node receiving this notification
	 * should perform any necessary updates to remain in synch
	 * with the tree (e.g. clearing out or replacing any references
	 * to the removed node or any of the removed node's descendants).
	 * @see #isDescendantOf(Node)
	 */
	public void nodeRemoved(Node node) {
		for (Iterator<Node> stream = this.children(); stream.hasNext(); ) {
			Node child = stream.next();		// pull out the child to ease debugging
			child.nodeRemoved(node);
		}
	// when you override this method, don't forget to include:
	//	super.nodeRemoved(node);
	}

	/**
	 * convenience method
	 * return whether node1 is a descendant of node2;
	 * node1 can be null
	 */
	protected boolean nodeIsDescendantOf(Node node1, Node node2) {
		return (node1 != null) && node1.isDescendantOf(node2);
	}

	/**
	 * INTRA-TREE API
	 * This is a general notification that the specified node has been
	 * renamed. The node receiving this notification should mark its
	 * branch dirty if necessary (i.e. it references the renamed node
	 * or one of its descendants). This method is of particular concern
	 * to Handles.
	 * @see #isDescendantOf(Node)
	 */
	public void nodeRenamed(Node node) {
		for (Iterator<Node> stream = this.children(); stream.hasNext(); ) {
			Node child = stream.next();		// pull out the child to ease debugging
			child.nodeRenamed(node);
		}
	// when you override this method, don't forget to include:
	//	super.nodeRenamed(node);
	}
	
	
	// ********** user comment **********

	/**
	 * Return the object's user comment.
	 */
	public final String comment() {
		return this.comment;
	}

	/**
	 * Set the object's user comment.
	 */
	public final void setComment(String comment) {
		Object old = this.comment;
		this.comment = comment;
		this.firePropertyChanged(COMMENT_PROPERTY, old, comment);
	}


	// ********** change support **********

	/**
	 * An aspect of the node has changed:
	 * 	- if it is a persistent aspect, mark the object dirty
	 * 	- if it is a significant aspect, validate the object
	 */
	protected void aspectChanged(String aspectName) {
		if (this.aspectIsPersistent(aspectName)) {
			// System.out.println(Thread.currentThread() + " dirty change: " + this + ": " + aspectName);
			this.markDirty();
		}
		if (this.aspectChangeRequiresValidation(aspectName)) {
			// System.out.println(Thread.currentThread() + " validation change: " + this + ": " + aspectName);
			this.validate();
		}
	}

	protected void validate() {
		this.getValidator().validate();
	}

	/**
	 * INTRA-TREE API
	 * Return a validator that will be invoked whenever a
	 * "validated" aspect of the node tree changes.
	 * Typically only the root node directly holds a validator.
	 * NB: Root node model implementations will need to override this method.
	 */
	public Node.Validator getValidator() {
		if (this.parent == null) {
			throw new IllegalStateException("This node should not be firing change events during its construction."); //$NON-NLS-1$
		}
		return this.parent.getValidator();
	}

	/**
	 * Set a validator that will be invoked whenever a
	 * "validated" aspect of the node tree changes.
	 * Typically only the root node directly holds a validator.
	 * NB: Root node model implementations will need to override this method.
	 */
	public void setValidator(Node.Validator validator) {
		if (this.parent == null) {
			throw new IllegalStateException("This root node should implement #setValidator(Node.Validator)."); //$NON-NLS-1$
		}
		throw new UnsupportedOperationException("Only root nodes implement #setValidator(Node.Validator)."); //$NON-NLS-1$
	}


	// ********** dirty flag support **********

	/**
	 * Return whether any persistent aspects of the object
	 * have changed since the object was last read or saved.
	 * This does NOT include changes to the object's descendants.
	 */
	public final boolean isDirty() {
		return this.dirty;
	}

	/**
	 * Return whether any persistent aspects of the object,
	 * or any of its descendants, have changed since the object and
	 * its descendants were last read or saved.
	 */
	public final boolean isDirtyBranch() {
		return this.dirtyBranch;
	}

	/**
	 * Return whether the object is unmodified
	 * since it was last read or saved.
	 * This does NOT include changes to the object's descendants.
	 */
	public final boolean isClean() {
		return ! this.dirty;
	}

	/**
	 * Return whether the object and all of its descendants
	 * are unmodified since the object and
	 * its descendants were last read or saved.
	 */
	public final boolean isCleanBranch() {
		return ! this.dirtyBranch;
	}

	/**
	 * Set the dirty branch flag setting. This is set to true
	 * when either the object or one of its descendants becomes dirty.
	 */
	private void setIsDirtyBranch(boolean dirtyBranch) {
		boolean old = this.dirtyBranch;
		this.dirtyBranch = dirtyBranch;
		this.firePropertyChanged(DIRTY_BRANCH_PROPERTY, old, dirtyBranch);
	}

	/**
	 * Mark the object as dirty and as a dirty branch.
	 * An object is marked dirty when either a "persistent" attribute
	 * has changed or its save location has changed.
	 */
	private void markDirty() {
		this.dirty = true;
		this.markBranchDirty();
	}

	/**
	 * INTRA-TREE API
	 * Mark the node and its parent as dirty branches.
	 * This message is propagated up the containment
	 * tree when a particular node becomes dirty.
	 */
	public void markBranchDirty() {
		// short-circuit any unnecessary propagation
		if (this.dirtyBranch) {
			// if this is already a dirty branch, the parent must be also
			return;
		}

		this.setIsDirtyBranch(true);
		this.markParentBranchDirty();
	}

	protected void markParentBranchDirty() {
		if (this.parent != null) {
			this.parent.markBranchDirty();
		}
	}

	/**
	 * Mark the object and all its descendants as dirty.
	 * This is used when the save location of some
	 * top-level object is changed and the entire
	 * containment tree must be marked dirty so it
	 * will be written out.
	 */
	public final void markEntireBranchDirty() {
		this.markDirty();
		for (Iterator<Node> stream = this.children(); stream.hasNext(); ) {
			Node child = stream.next();		// pull out the child to ease debugging
			child.markEntireBranchDirty();
		}
	}

	/**
	 * Mark the object and all its descendants as clean.
	 * Then notify the object's parent that it (the parent)
	 * might now be a clean branch also.
	 * Typically used when the object has just been
	 * read in or written out.
	 */
	public final void markEntireBranchClean() {
		this.cascadeMarkEntireBranchClean();
		this.markParentBranchCleanIfPossible();
	}

	protected void markParentBranchCleanIfPossible() {
		if (this.parent != null) {
			this.parent.markBranchCleanIfPossible();
		}
	}

	/**
	 * INTRA-TREE API
	 * Mark the node and all its descendants as clean.
	 * Typically used when the node has just been
	 * read in or written out.
	 * This method is for internal use only; it is not for
	 * client use.
	 * Not the best of method names.... :-(
	 */
	public final void cascadeMarkEntireBranchClean() {
		for (Iterator<Node> stream = this.children(); stream.hasNext(); ) {
			Node child = stream.next();		// pull out the child to ease debugging
			child.cascadeMarkEntireBranchClean();
		}
		this.dirty = false;
		this.setIsDirtyBranch(false);
	}

	/**
	 * INTRA-TREE API
	 * A child node's branch has been marked clean. If the node
	 * itself is clean and if all of its children are also clean, the
	 * node's branch can be marked clean. Then, if the node's
	 * branch is clean, the node will notify its parent that it might
	 * be clean also. This message is propagated up the containment
	 * tree when a particular node becomes clean.
	 */
	public final void markBranchCleanIfPossible() {
		// short-circuit any unnecessary propagation
		if (this.dirty) {
			// if the object is "locally" dirty, it is still a dirty branch
			return;
		}

		for (Iterator<Node> stream = this.children(); stream.hasNext(); ) {
			Node child = stream.next();		// pull out the child to ease debugging
			if (child.isDirtyBranch()) {
				return;
			}
		}

		this.setIsDirtyBranch(false);
		this.markParentBranchCleanIfPossible();
	}

	private boolean aspectIsPersistent(String aspectName) {
		return ! this.aspectIsTransient(aspectName);
	}

	private boolean aspectIsTransient(String aspectName) {
		return this.transientAspectNames().contains(aspectName);
	}

	/**
	 * Return a set of the object's transient aspect names.
	 * These are the aspects that, when they change, will NOT cause the
	 * object to be marked dirty.
	 * If you need instance-based calculation of your transient aspects,
	 * override this method. If class-based calculation is sufficient,
	 * override #addTransientAspectNamesTo(Set).
	 */
	protected final Set<String> transientAspectNames() {
		synchronized (transientAspectNameSets) {
			HashSet<String> transientAspectNames = transientAspectNameSets.get(this.getClass());
			if (transientAspectNames == null) {
				transientAspectNames = new HashSet<String>();
				this.addTransientAspectNamesTo(transientAspectNames);
				transientAspectNameSets.put(this.getClass(), transientAspectNames);
			}
			return transientAspectNames;
		}
	}

	/**
	 * Add the object's transient aspect names to the specified set.
	 * These are the aspects that, when they change, will NOT cause the
	 * object to be marked dirty.
	 * If class-based calculation of your transient aspects is sufficient,
	 * override this method. If you need instance-based calculation,
	 * override #transientAspectNames().
	 */
	protected void addTransientAspectNamesTo(Set<String> transientAspectNames) {
		transientAspectNames.add(DIRTY_BRANCH_PROPERTY);
		transientAspectNames.add(BRANCH_PROBLEMS_LIST);
		transientAspectNames.add(HAS_BRANCH_PROBLEMS_PROPERTY);
	// when you override this method, don't forget to include:
	//	super.addTransientAspectNamesTo(transientAspectNames);
	}

	/**
	 * Return the dirty nodes in the object's branch of the tree,
	 * including the node itself (if appropriate).
	 * Only really used for testing and debugging.
	 */
	public final Iterator<Node> allDirtyNodes() {
		return new FilteringIterator<Node>(this.allNodes()) {
			@Override
			protected boolean accept(Node node) {
				return (node instanceof AbstractNode) && ((AbstractNode) node).isDirty();
			}
		};
	}


	// ********** problems **********

	/**
	 * Return the node's problems.
	 * This does NOT include the problems of the node's descendants.
	 * @see #branchProblems()
	 */
	public final Iterator<Problem> problems() {
		return new CloneIterator<Problem>(this.problems);	// removes are not allowed
	}

	/**
	 * Return the size of the node's problems.
	 * This does NOT include the problems of the node's descendants.
	 * @see #branchProblemsSize()
	 */
	public final int problemsSize() {
		return this.problems.size();
	}

	/**
	 * Return whether the node has problems
	 * This does NOT include the problems of the node's descendants.
	 * @see #hasBranchProblems()
	 */
	public final boolean hasProblems() {
		return ! this.problems.isEmpty();
	}

	/**
	 * Return all the node's problems along with all the
	 * node's descendants' problems.
	 */
	public final ListIterator<Problem> branchProblems() {
		return new CloneListIterator<Problem>(this.branchProblems);	// removes are not allowed
	}

	/**
	 * Return the size of all the node's problems along with all the
	 * node's descendants' problems.
	 */
	public final int branchProblemsSize() {
		return this.branchProblems.size();
	}

	/**
	 * Return whether the node or any of its descendants have problems.
	 */
	public final boolean hasBranchProblems() {
		return ! this.branchProblems.isEmpty();
	}

	public final boolean containsBranchProblem(Problem problem) {
		return this.branchProblems.contains(problem);
	}

	protected final Problem buildProblem(String messageKey, int messageType, Object... messageArguments) {
		return new DefaultProblem(this, messageKey, messageType, messageArguments);
	}

	protected final Problem buildProblem(String messageKey, int messageType) {
		return this.buildProblem(messageKey, messageType, EMPTY_PROBLEM_MESSAGE_ARGUMENTS);
	}

	/**
	 * Validate the node and all of its descendants,
	 * and update their sets of "branch" problems.
	 * If the node's "branch" problems have changed,
	 * notify the node's parent.
	 */
	public void validateBranch() {
		if (this.validateBranchInternal()) {
			// if our "branch" problems have changed, then
			// our parent must rebuild its "branch" problems also
			this.rebuildParentBranchProblems();
		}
	}

	protected void rebuildParentBranchProblems() {
		if (this.parent != null) {
			this.parent.rebuildBranchProblems();
		}
	}

	/**
	 * INTRA-TREE API
	 * Validate the node and all of its descendants,
	 * and update their sets of "branch" problems.
	 * Return true if the collection of "branch" problems has changed.
	 * This method is for internal use only; it is not for
	 * client use.
	 */
	public boolean validateBranchInternal() {
		// rebuild "branch" problems in children first
		for (Iterator<Node> stream = this.children(); stream.hasNext(); ) {
			Node child = stream.next();		// pull out the child to ease debugging
			// ignore the return value because we are going to rebuild our "branch"
			// problems no matter what, to see if they have changed
			child.validateBranchInternal();
		}

		this.problems.clear();
		this.addProblemsTo(this.problems);

		return this.checkBranchProblems();
	}

	/**
	 * Check for any problems and add them to the specified list.
	 * This method should ONLY add problems for this particular node;
	 * it should NOT add problems for any of this node's descendants
	 * or ancestors. (Although there will be times when it is debatable
	 * as to which node a problem "belongs" to....)
	 * 
	 * NB: This method should NOT modify ANY part of the node's state!
	 * It is a READ-ONLY behavior. ONLY the list of current problems
	 * passed in to the method should be modified.
	 */
	protected void addProblemsTo(@SuppressWarnings("unused") List<Problem> currentProblems) {
		// The default is to do nothing.
		// When you override this method, don't forget to include:
	//	super.addProblemsTo(currentProblems);
	}

	/**
	 * Rebuild the "branch" problems and return whether they have
	 * changed.
	 * NB: The entire collection of "branch" problems must be re-calculated
	 * with EVERY "significant" change - we cannot keep it in synch via
	 * change notifications because if a descendant with problems is
	 * removed or replaced we will not receive notification that its
	 * problems were removed from our "branch" problems.
	 */
	private boolean checkBranchProblems() {
		Vector<Problem> oldBranchProblems = new Vector<Problem>(this.branchProblems);
		int oldSize = this.branchProblems.size();

		this.branchProblems.clear();
		this.branchProblems.addAll(this.problems);
		for (Iterator<Node> stream = this.children(); stream.hasNext(); ) {
			Node child = stream.next();		// pull out the child to ease debugging
			child.addBranchProblemsTo(this.branchProblems);
		}

		// if the size has changed to or from zero, our virtual flag has changed
		int newSize = this.branchProblems.size();
		if ((oldSize == 0) && (newSize != 0)) {
			this.firePropertyChanged(HAS_BRANCH_PROBLEMS_PROPERTY, false, true);
		} else if ((oldSize != 0) && (newSize == 0)) {
			this.firePropertyChanged(HAS_BRANCH_PROBLEMS_PROPERTY, true, false);
		}

		if (oldBranchProblems.equals(this.branchProblems)) {
			return false;		// our "branch" problems did not change
		}
		// our "branch" problems changed
		this.fireListChanged(BRANCH_PROBLEMS_LIST, this.branchProblems);
		return true;
	}

	/**
	 * INTRA-TREE API
	 * Add all the problems of the node and all
	 * the problems of its descendants to the
	 * specified collection.
	 */
	public final void addBranchProblemsTo(List<Problem> list) {
		list.addAll(this.branchProblems);
	}

	/**
	 * INTRA-TREE API
	 * A child node's "branch" problems changed;
	 * therefore the node's "branch" problems have changed also and
	 * must be rebuilt.
	 */
	public final void rebuildBranchProblems() {
		if ( ! this.checkBranchProblems()) {
			throw new IllegalStateException("we should not get here unless our \"branch\" problems have changed"); //$NON-NLS-1$
		}
		this.rebuildParentBranchProblems();
	}

	/**
	 * Clear the node's "branch" problems and the "branch"
	 * problems of all of its descendants.
	 * If the node's "branch" problems have changed,
	 * notify the node's parent.
	 */
	public final void clearAllBranchProblems() {
		if (this.clearAllBranchProblemsInternal()) {
			// if our "branch" problems have changed, then
			// our parent must rebuild its "branch" problems also
			this.rebuildParentBranchProblems();
		}
	}

	/**
	 * INTRA-TREE API
	 * Clear the node's "branch" problems and the "branch"
	 * problems of all of its descendants.
	 * Return true if the collection of "branch" problems has changed.
	 * This method is for internal use only; it is not for
	 * client use.
	 */
	public final boolean clearAllBranchProblemsInternal() {
		if (this.branchProblems.isEmpty()) {
			return false;
		}
		for (Iterator<Node> stream = this.children(); stream.hasNext(); ) {
			Node child = stream.next();		// pull out the child to ease debugging
			// ignore the return value because we are going to clear our "branch"
			// problems no matter what
			child.clearAllBranchProblemsInternal();
		}
		this.problems.clear();
		this.branchProblems.clear();
		this.firePropertyChanged(HAS_BRANCH_PROBLEMS_PROPERTY, true, false);
		this.fireListChanged(BRANCH_PROBLEMS_LIST, this.branchProblems);
		return true;
	}

	/**
	 * Return whether a change to specified aspect requires a re-validation
	 * of the node's tree.
	 */
	private boolean aspectChangeRequiresValidation(String aspectName) {
		return ! this.aspectChangeDoesNotRequireValidation(aspectName);
	}

	private boolean aspectChangeDoesNotRequireValidation(String aspectName) {
		return this.nonValidatedAspectNames().contains(aspectName);
	}

	/**
	 * Return a set of the object's "non-validated" aspect names.
	 * These are the aspects that, when they change, will NOT cause the
	 * object (or its containing tree) to be validated, i.e. checked for problems.
	 * If you need instance-based calculation of your "non-validated" aspects,
	 * override this method. If class-based calculation is sufficient,
	 * override #addNonValidatedAspectNamesTo(Set).
	 */
	protected final Set<String> nonValidatedAspectNames() {
		synchronized (nonValidatedAspectNameSets) {
			HashSet<String> nonValidatedAspectNames = nonValidatedAspectNameSets.get(this.getClass());
			if (nonValidatedAspectNames == null) {
				nonValidatedAspectNames = new HashSet<String>();
				this.addNonValidatedAspectNamesTo(nonValidatedAspectNames);
				nonValidatedAspectNameSets.put(this.getClass(), nonValidatedAspectNames);
			}
			return nonValidatedAspectNames;
		}
	}

	/**
	 * Add the object's "non-validated" aspect names to the specified set.
	 * These are the aspects that, when they change, will NOT cause the
	 * object (or its containing tree) to be validated, i.e. checked for problems.
	 * If class-based calculation of your "non-validated" aspects is sufficient,
	 * override this method. If you need instance-based calculation,
	 * override #nonValidatedAspectNames().
	 */
	protected void addNonValidatedAspectNamesTo(Set<String> nonValidatedAspectNames) {
		nonValidatedAspectNames.add(COMMENT_PROPERTY);
		nonValidatedAspectNames.add(DIRTY_BRANCH_PROPERTY);
		nonValidatedAspectNames.add(BRANCH_PROBLEMS_LIST);
		nonValidatedAspectNames.add(HAS_BRANCH_PROBLEMS_PROPERTY);
	// when you override this method, don't forget to include:
	//	super.addNonValidatedAspectNamesTo(nonValidatedAspectNames);
	}


	// ********** display methods **********

	/**
	 * Return a developer-friendly String. If you want something useful for
	 * displaying in a user interface, use #displayString().
	 * If you want to give more information in your #toString(),
	 * override #toString(StringBuilder sb). 
	 * Whatever you add to that string buffer will show up between the parentheses.
	 * @see AbstractModel#toString(StringBuilder sb)
	 * @see #displayString()
	 */
	@Override
	public final String toString() {
		return super.toString();
	}

}
