/*******************************************************************************
 * Copyright (c) 2000, 2014 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.core.internal.dtree;

import org.eclipse.core.internal.utils.Messages;
import org.eclipse.core.internal.utils.StringPool;
import org.eclipse.core.runtime.*;

/**
 * Externally, a <code>DeltaDataTree</code> appears to have the same content as
 * a standard data tree.  Internally, the delta tree may be complete, or it may
 * just indicate the changes between itself and its parent.
 *
 * <p>Nodes that exist in the parent but do not exist in the delta, are represented
 * as instances of <code>DeletedNode</code>.  Nodes that are identical in the parent
 * and the delta, but have differences in their subtrees, are represented as
 * instances of <code>NoDataDeltaNode</code> in the delta tree.  Nodes that differ
 * between parent and delta are instances of <code>DataDeltaNode</code>.  However,
 * the <code>DataDeltaNode</code> only contains the children whose subtrees differ
 * between parent and delta.
 *
 * A delta tree algebra is used to manipulate sets of delta trees.  Given two trees,
 * one can obtain the delta between the two using the method
 * <code>forwardDeltaWith(aTree)</code>.  Given a tree and a delta, one can assemble
 * the complete tree that the delta represents using the method <code>
 * assembleWithForwardDelta</code>.  Refer to the public API methods of this class
 * for further details.
 */

public class DeltaDataTree extends AbstractDataTree {
	private AbstractDataTreeNode rootNode;
	private DeltaDataTree parent;

	/**
	 * Creates a new empty tree.
	 */
	public DeltaDataTree() {
		this.empty();
	}

	/**
	 * Creates a new tree.
	 * @param rootNode
	 *	root node of new tree.
	 */
	public DeltaDataTree(AbstractDataTreeNode rootNode) {
		this.rootNode = rootNode;
		this.parent = null;
	}

	protected DeltaDataTree(AbstractDataTreeNode rootNode, DeltaDataTree parent) {
		this.rootNode = rootNode;
		this.parent = parent;
	}

	/**
	 * Adds a child to the tree.
	 *
	 * @param parentKey parent for new child.
	 * @param localName name of child.
	 * @param childNode child node.
	 */
	protected void addChild(IPath parentKey, String localName, AbstractDataTreeNode childNode) {
		if (!includes(parentKey))
			handleNotFound(parentKey);
		childNode.setName(localName);
		this.assembleNode(parentKey, new NoDataDeltaNode(parentKey.lastSegment(), childNode));
	}

	/**
	 * Returns the tree as a backward delta.  If the delta is applied to the tree it
	 * will produce its parent. The receiver must have a forward
	 * delta representation. I.e.:  Call the receiver's parent A,
	 * and the receiver B.  The receiver's representation is A-&gt;B.
	 * Returns the delta A&lt;-B.  The result is equivalent to A, but has B as its parent.
	 */
	DeltaDataTree asBackwardDelta() {
		if (getParent() == null)
			return newEmptyDeltaTree();
		return new DeltaDataTree(getRootNode().asBackwardDelta(this, getParent(), rootKey()), this);
	}

	/**
	 * This method can only be called on a comparison tree created
	 * using DeltaDataTree.compareWith().  This method flips the orientation
	 * of the given comparison tree, so that additions become removals,
	 * and vice-versa.  This method destructively changes the tree
	 * as opposed to making a copy.
	 */
	public DeltaDataTree asReverseComparisonTree(IComparator comparator) {
		/* don't reverse the root node if it's the absolute root (name==null) */
		if (rootNode.getName() == null) {
			AbstractDataTreeNode[] children = rootNode.getChildren();
			int nextChild = 0;
			for (AbstractDataTreeNode c : children) {
				AbstractDataTreeNode newChild = c.asReverseComparisonNode(comparator);
				if (newChild != null) {
					children[nextChild++] = newChild;
				}
			}

			if (nextChild < children.length) {
				AbstractDataTreeNode[] newChildren = new AbstractDataTreeNode[nextChild];
				System.arraycopy(children, 0, newChildren, 0, nextChild);
				rootNode.setChildren(newChildren);
			}
		} else {
			rootNode.asReverseComparisonNode(comparator);
		}
		return this;
	}

	/**
	 * Replaces a node in the tree with the result of assembling the node
	 * with the given delta node (which represents a forward delta on
	 * the existing node).
	 *
	 * @param key key of the node to replace.
	 * @param deltaNode delta node to use to assemble the new node.
	 */
	protected void assembleNode(IPath key, AbstractDataTreeNode deltaNode) {
		rootNode = rootNode.assembleWith(deltaNode, key, 0);
	}

	/**
	 * Assembles the receiver with the given delta tree and answer
	 * the resulting, mutable source tree.  The given delta tree must be a
	 * forward delta based on the receiver (i.e. missing information is taken from
	 * the receiver).  This operation is used to coalesce delta trees.
	 *
	 * <p>In detail, suppose that c is a forward delta over source tree a.
	 * Let d := a assembleWithForwardDelta: c.
	 * d has the same content as c, and is represented as a delta tree
	 * whose parent is the same as a's parent.
	 *
	 * <p>In general, if c is represented as a chain of deltas of length n,
	 * then d is represented as a chain of length n-1.
	 *
	 * <p>So if a is a complete tree (i.e., has no parent, length=0), then d
	 * will be a complete tree too.
	 *
	 * <p>Corollary: (a assembleWithForwardDelta: (a forwardDeltaWith: b)) = b
	 */
	public DeltaDataTree assembleWithForwardDelta(DeltaDataTree deltaTree) {
		return new DeltaDataTree(getRootNode().assembleWith(deltaTree.getRootNode()), this);
	}

	/**
	 * Compares this tree with another tree, starting from the given path.  The
	 * given path will be the root node of the returned tree.  Both this
	 * tree and other tree must contain the given path.
	 */
	protected DeltaDataTree basicCompare(DeltaDataTree other, IComparator comparator, IPath path) {
		DeltaDataTree newTree;
		if (this == other) {
			newTree = new DeltaDataTree();
			newTree.setData(Path.ROOT, new NodeComparison(null, null, 0, 0));
		} else if (other.hasAncestor(this)) {
			AbstractDataTreeNode assembled = other.searchNodeAt(path);
			DeltaDataTree tree = other;

			/* Iterate through the receiver's ancestors until the receiver is reached */
			while ((tree = tree.getParent()) != this) {
				//ancestor may not contain the given path
				AbstractDataTreeNode treeNode = tree.searchNodeAt(path);
				if (treeNode != null) {
					assembled = treeNode.assembleWith(assembled);
				}
			}
			AbstractDataTreeNode comparedRoot = assembled.compareWithParent(path, this, comparator);
			newTree = new DeltaDataTree(comparedRoot);
		} else if (this.hasAncestor(other)) {
			AbstractDataTreeNode assembled = this.asBackwardDelta().searchNodeAt(path);
			DeltaDataTree tree = this;

			/* Iterate through the receiver's ancestors until the other tree is reached */
			while ((tree = tree.getParent()) != other) {
				assembled = assembled.assembleWith(tree.asBackwardDelta().searchNodeAt(path));
			}
			AbstractDataTreeNode comparedRoot = assembled.compareWithParent(path, this, comparator);
			newTree = new DeltaDataTree(comparedRoot);
		} else {
			//revert to naive comparison
			DataTreeNode thisCompleteRoot = (DataTreeNode) this.copyCompleteSubtree(path);
			DataTreeNode otherCompleteRoot = (DataTreeNode) other.copyCompleteSubtree(path);
			AbstractDataTreeNode comparedRoot = thisCompleteRoot.compareWith(otherCompleteRoot, comparator);
			newTree = new DeltaDataTree(comparedRoot);
		}
		newTree.immutable();
		return newTree;
	}

	/**
	 * Collapses this tree so that the given ancestor becomes its
	 * immediate parent.  Afterwards, this tree will still have exactly the
	 * same contents, but its internal structure will be compressed.
	 *
	 * <p> This operation should be used to collapse chains of
	 * delta trees that don't contain interesting intermediate states.
	 *
	 * <p>This is a destructive operation, since it modifies the structure of this
	 * tree instance.  This tree must be immutable at the start of this operation,
	 * and will be immutable afterwards.
	 * @return this tree.
	 */
	public DeltaDataTree collapseTo(DeltaDataTree collapseTo, IComparator comparator) {
		if (this == collapseTo || getParent() == collapseTo) {
			//already collapsed
			return this;
		}
		//collapse my tree to be a forward delta of the parent's tree.
		//c will have the same content as this tree, but its parent will be "parent".
		DeltaDataTree c = collapseTo.forwardDeltaWith(this, comparator);

		//update my internal root node and parent pointers.
		this.parent = collapseTo;
		this.rootNode = c.rootNode;
		return this;
	}

	/**
	 * Returns a DeltaDataTree that describes the differences between
	 * this tree and "other" tree.  Each node of the returned tree
	 * will contain a NodeComparison object that describes the differences
	 * between the two trees.
	 */
	public DeltaDataTree compareWith(DeltaDataTree other, IComparator comparator) {

		DeltaDataTree newTree;
		if (this == other) {
			newTree = new DeltaDataTree();
			newTree.setData(Path.ROOT, new NodeComparison(null, null, 0, 0));
		} else if (other.hasAncestor(this)) {

			AbstractDataTreeNode assembled = other.getRootNode();
			DeltaDataTree tree = other;

			/* Iterate through the receiver's ancestors until the receiver is reached */
			while ((tree = tree.getParent()) != this) {
				assembled = tree.getRootNode().assembleWith(assembled);
			}
			AbstractDataTreeNode comparedRoot = assembled.compareWithParent(rootKey(), this, comparator);
			newTree = new DeltaDataTree(comparedRoot);
		} else if (this.hasAncestor(other)) {
			AbstractDataTreeNode assembled = this.asBackwardDelta().getRootNode();
			DeltaDataTree tree = this;

			/* Iterate through the receiver's ancestors until the other tree is reached */
			while ((tree = tree.getParent()) != other) {
				assembled = assembled.assembleWith(tree.asBackwardDelta().getRootNode());
			}
			AbstractDataTreeNode comparedRoot = assembled.compareWithParent(rootKey(), this, comparator);
			newTree = new DeltaDataTree(comparedRoot);
		} else {
			//revert to naive comparison if trees have no common ancestry
			DataTreeNode thisCompleteRoot = (DataTreeNode) this.copyCompleteSubtree(rootKey());
			DataTreeNode otherCompleteRoot = (DataTreeNode) other.copyCompleteSubtree(rootKey());
			AbstractDataTreeNode comparedRoot = thisCompleteRoot.compareWith(otherCompleteRoot, comparator);
			newTree = new DeltaDataTree(comparedRoot);
		}
		newTree.immutable();
		return newTree;
	}

	/**
	 * Compares this tree with another tree, starting from the given path.  The
	 * given path will be the root node of the returned tree.
	 */
	public DeltaDataTree compareWith(DeltaDataTree other, IComparator comparator, IPath path) {
		/* need to figure out if trees really contain the given path */
		if (this.includes(path)) {
			if (other.includes(path))
				return basicCompare(other, comparator, path);
			/* only exists in this tree */
			return new DeltaDataTree(AbstractDataTreeNode.convertToRemovedComparisonNode(this.copyCompleteSubtree(path), comparator.compare(this.getData(path), null)));
		}
		if (other.includes(path))
			/* only exists in other tree */
			return new DeltaDataTree(AbstractDataTreeNode.convertToAddedComparisonNode(other.copyCompleteSubtree(path), comparator.compare(null, other.getData(path))));
		/* doesn't exist in either tree */
		return DeltaDataTree.createEmptyDelta();
	}

	/**
	 * Returns a copy of the tree which shares its instance variables.
	 */
	@Override
	protected AbstractDataTree copy() {
		return new DeltaDataTree(rootNode, parent);
	}

	/**
	 * Returns a complete node containing the contents of a subtree of the tree.
	 *
	 * @param key
	 *	key of subtree to copy
	 */
	@Override
	public AbstractDataTreeNode copyCompleteSubtree(IPath key) {
		AbstractDataTreeNode node = searchNodeAt(key);
		if (node == null) {
			handleNotFound(key);
			return null;
		}
		if (node.isDelta())
			return naiveCopyCompleteSubtree(key);
		//copy the node in case the user wants to hammer the subtree name
		return node.copy();
	}

	/**
	 * @see AbstractDataTree#createChild(IPath, String)
	 */
	@Override
	public void createChild(IPath parentKey, String localName) {
		createChild(parentKey, localName, null);
	}

	/**
	 * @see AbstractDataTree#createChild(IPath, String, Object)
	 */
	@Override
	public void createChild(IPath parentKey, String localName, Object data) {
		if (isImmutable())
			handleImmutableTree();
		addChild(parentKey, localName, new DataTreeNode(localName, data));
	}

	/**
	 * Returns a delta data tree that represents an empty delta.
	 * (i.e. it represents a delta on another (unspecified) tree,
	 * but introduces no changes).
	 */
	static DeltaDataTree createEmptyDelta() {

		DeltaDataTree newTree = new DeltaDataTree();
		newTree.emptyDelta();
		return newTree;
	}

	/**
	 * Creates and returns an instance of the receiver.
	 * @see AbstractDataTree#createInstance()
	 */
	@Override
	protected AbstractDataTree createInstance() {
		return new DeltaDataTree();
	}

	/**
	 * @see AbstractDataTree#createSubtree(IPath, AbstractDataTreeNode)
	 */
	@Override
	public void createSubtree(IPath key, AbstractDataTreeNode node) {
		if (isImmutable())
			handleImmutableTree();
		if (key.isRoot()) {
			setParent(null);
			setRootNode(node);
		} else {
			addChild(key.removeLastSegments(1), key.lastSegment(), node);
		}
	}

	/**
	 * @see AbstractDataTree#deleteChild(IPath, String)
	 */
	@Override
	public void deleteChild(IPath parentKey, String localName) {
		if (isImmutable())
			handleImmutableTree();
		/* If the child does not exist */
		IPath childKey = parentKey.append(localName);
		if (!includes(childKey))
			handleNotFound(childKey);
		assembleNode(parentKey, new NoDataDeltaNode(parentKey.lastSegment(), new DeletedNode(localName)));
	}

	/**
	 * Initializes the receiver so that it is a complete, empty tree.
	 * @see AbstractDataTree#empty()
	 */
	@Override
	public void empty() {
		rootNode = new DataTreeNode(null, null);
		parent = null;
	}

	/**
	 * Initializes the receiver so that it represents an empty delta.
	 * (i.e. it represents a delta on another (unspecified) tree,
	 * it introduces no changes).  The parent is left unchanged.
	 */
	void emptyDelta() {
		rootNode = new NoDataDeltaNode(null);
	}

	/**
	 * Returns a node of the tree if it is present, otherwise returns null
	 *
	 * @param key
	 *	key of node to find
	 */
	public AbstractDataTreeNode findNodeAt(IPath key) {
		AbstractDataTreeNode node = rootNode;
		int segmentCount = key.segmentCount();
		for (int i = 0; i < segmentCount; i++) {
			node = node.childAtOrNull(key.segment(i));
			if (node == null)
				return null;
		}
		return node;
	}

	/**
	 * Returns a forward delta between the receiver and the given source tree,
	 * using the given comparer to compare data objects.
	 * The result describes the changes which, if assembled with the receiver,
	 * will produce the given source tree.
	 * In more detail, let c = a.forwardDeltaWith(b).
	 * c has the same content as b, but is represented as a delta tree with a as the parent.
	 * Also, c is immutable.
	 *
	 * There is no requirement that a and b be related, although it is usually more
	 * efficient if they are. The node keys are used as the basis of correlation
	 * between trees.
	 *
	 * Note that if b is already represented as a delta over a,
	 * then c will have the same internal structure as b.
	 * Thus the very common case of previous forwardDeltaWith: current
	 * is actually very fast when current is a modification of previous.
	 *
	 * @param sourceTree second delta tree to create a delta between
	 * @param comparer the comparer used to compare data objects
	 * @return the new delta
	 */
	public DeltaDataTree forwardDeltaWith(DeltaDataTree sourceTree, IComparator comparer) {
		DeltaDataTree newTree;
		if (this == sourceTree) {
			newTree = this.newEmptyDeltaTree();
		} else if (sourceTree.hasAncestor(this)) {
			AbstractDataTreeNode assembled = sourceTree.getRootNode();
			DeltaDataTree treeParent = sourceTree;

			/* Iterate through the sourceTree's ancestors until the receiver is reached */
			while ((treeParent = treeParent.getParent()) != this) {
				assembled = treeParent.getRootNode().assembleWith(assembled);
			}
			newTree = new DeltaDataTree(assembled, this);
			newTree.simplify(comparer);
		} else if (this.hasAncestor(sourceTree)) {
			//create the delta backwards and then reverse it
			newTree = sourceTree.forwardDeltaWith(this, comparer);
			newTree = newTree.asBackwardDelta();
		} else {
			DataTreeNode thisCompleteRoot = (DataTreeNode) this.copyCompleteSubtree(rootKey());
			DataTreeNode sourceTreeCompleteRoot = (DataTreeNode) sourceTree.copyCompleteSubtree(rootKey());
			AbstractDataTreeNode deltaRoot = thisCompleteRoot.forwardDeltaWith(sourceTreeCompleteRoot, comparer);
			newTree = new DeltaDataTree(deltaRoot, this);
		}
		newTree.immutable();
		return newTree;
	}

	/**
	 * @see AbstractDataTree#getChildCount(IPath)
	 */
	@Override
	public int getChildCount(IPath parentKey) {
		return getChildNodes(parentKey).length;
	}

	/**
	 * Returns the child nodes of a node in the tree.
	 */
	protected AbstractDataTreeNode[] getChildNodes(IPath parentKey) {

		/* Algorithm:
		 *   for each delta in chain (going backwards),
		 *     get list of child nodes, if any in delta
		 *     assemble with previously seen list, if any
		 *     break when complete tree found,
		 *   report error if parent is missing or has been deleted
		 */

		AbstractDataTreeNode[] childNodes = null;
		int keyLength = parentKey.segmentCount();
		for (DeltaDataTree tree = this; tree != null; tree = tree.parent) {
			AbstractDataTreeNode node = tree.rootNode;
			boolean complete = !node.isDelta();
			for (int i = 0; i < keyLength; i++) {
				node = node.childAtOrNull(parentKey.segment(i));
				if (node == null) {
					break;
				}
				if (!node.isDelta()) {
					complete = true;
				}
			}
			if (node != null) {
				if (node.isDeleted()) {
					break;
				}
				if (childNodes == null) {
					childNodes = node.children;
				} else {
					// Be sure to assemble(old, new) rather than (new, old).
					// Keep deleted nodes if we haven't encountered the complete node yet.
					childNodes = AbstractDataTreeNode.assembleWith(node.children, childNodes, !complete);
				}
			}
			if (complete) {
				if (childNodes != null) {
					return childNodes;
				}
				// Not found, but complete node encountered, so should not check parent tree.
				break;
			}
		}
		if (childNodes != null) {
			// Some deltas carry info about children, but there is
			// no complete node against which they describe deltas.
			Assert.isTrue(false, Messages.dtree_malformedTree);
		}

		// Node is missing or has been deleted.
		handleNotFound(parentKey);
		return null;//should not get here
	}

	/**
	 * @see AbstractDataTree#getChildren(IPath)
	 */
	@Override
	public IPath[] getChildren(IPath parentKey) {
		AbstractDataTreeNode[] childNodes = getChildNodes(parentKey);
		int len = childNodes.length;
		if (len == 0)
			return NO_CHILDREN;
		IPath[] answer = new IPath[len];
		for (int i = 0; i < len; ++i)
			answer[i] = parentKey.append(childNodes[i].name);
		return answer;
	}

	/**
	 * Returns the data at a node of the tree.
	 *
	 * @param key
	 *	key of node for which to return data.
	 */
	@Override
	public Object getData(IPath key) {

		/* Algorithm:
		 *   for each delta in chain (going backwards),
		 *     get node, if any in delta
		 *	   if it carries data, return it
		 *     break when complete tree found
		 *   report error if node is missing or has been deleted
		 */

		int keyLength = key.segmentCount();
		for (DeltaDataTree tree = this; tree != null; tree = tree.parent) {
			AbstractDataTreeNode node = tree.rootNode;
			boolean complete = !node.isDelta();
			for (int i = 0; i < keyLength; i++) {
				node = node.childAtOrNull(key.segment(i));
				if (node == null) {
					break;
				}
				if (!node.isDelta()) {
					complete = true;
				}
			}
			if (node != null) {
				if (node.hasData()) {
					return node.getData();
				} else if (node.isDeleted()) {
					break;
				}
			}
			if (complete) {
				// Not found, but complete node encountered, so should not check parent tree.
				break;
			}
		}
		handleNotFound(key);
		return null; //can't get here
	}

	/**
	 * @see AbstractDataTree#getNameOfChild(IPath, int)
	 */
	@Override
	public String getNameOfChild(IPath parentKey, int index) {
		AbstractDataTreeNode[] childNodes = getChildNodes(parentKey);
		return childNodes[index].name;
	}

	/**
	 * Returns the local names for the children of a node of the tree.
	 *
	 * @see AbstractDataTree#getNamesOfChildren(IPath)
	 */
	@Override
	public String[] getNamesOfChildren(IPath parentKey) {
		AbstractDataTreeNode[] childNodes = getChildNodes(parentKey);
		int len = childNodes.length;
		String[] namesOfChildren = new String[len];
		for (int i = 0; i < len; ++i)
			namesOfChildren[i] = childNodes[i].name;
		return namesOfChildren;
	}

	/**
	 * Returns the parent of the tree.
	 */
	public DeltaDataTree getParent() {
		return parent;
	}

	/**
	 * Returns the root node of the tree.
	 */
	@Override
	protected AbstractDataTreeNode getRootNode() {
		return rootNode;
	}

	/**
	 * Returns true if the receiver's parent has the specified ancestor
	 *
	 * @param ancestor the ancestor in question
	 */
	protected boolean hasAncestor(DeltaDataTree ancestor) {
		DeltaDataTree myParent = this;
		while ((myParent = myParent.getParent()) != null) {
			if (myParent == ancestor) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Returns true if the receiver includes a node with
	 * the given key, false otherwise.
	 */
	@Override
	public boolean includes(IPath key) {
		return searchNodeAt(key) != null;
	}

	public boolean isEmptyDelta() {
		return rootNode.getChildren().length == 0;
	}

	/**
	 * Returns an object containing:
	 *  - the node key
	 * 	- a flag indicating whether the specified node was found
	 *  - the data for the node, if it was found
	 *
	 * @param key  key of node for which we want to retrieve data.
	 */
	@Override
	public DataTreeLookup lookup(IPath key) {
		int keyLength = key.segmentCount();
		for (DeltaDataTree tree = this; tree != null; tree = tree.parent) {
			AbstractDataTreeNode node = tree.rootNode;
			boolean complete = !node.isDelta();
			for (int i = 0; i < keyLength; i++) {
				node = node.childAtOrNull(key.segment(i));
				if (node == null) {
					break;
				}
				complete |= !node.isDelta();
			}
			if (node != null) {
				if (node.hasData()) {
					return DataTreeLookup.newLookup(key, true, node.getData(), tree == this);
				} else if (node.isDeleted()) {
					break;
				}
			}
			if (complete) {
				// Not found, but complete node encountered, so should not check parent tree.
				break;
			}
		}
		return DataTreeLookup.newLookup(key, false, null);
	}

	/**
	 * Returns an object containing:
	 *  - the node key
	 * 	- a flag indicating whether the specified node was found
	 *  - the data for the node, if it was found
	 *
	 * This is a case-insensitive variant of the <code>lookup</code>
	 * method.
	 *
	 * @param key  key of node for which we want to retrieve data.
	 */
	public DataTreeLookup lookupIgnoreCase(IPath key) {
		int keyLength = key.segmentCount();
		for (DeltaDataTree tree = this; tree != null; tree = tree.parent) {
			AbstractDataTreeNode node = tree.rootNode;
			boolean complete = !node.isDelta();
			for (int i = 0; i < keyLength; i++) {
				node = node.childAtIgnoreCase(key.segment(i));
				if (node == null) {
					break;
				}
				complete |= !node.isDelta();
			}
			if (node != null) {
				if (node.hasData()) {
					return DataTreeLookup.newLookup(key, true, node.getData(), tree == this);
				} else if (node.isDeleted()) {
					break;
				}
			}
			if (complete) {
				// Not found, but complete node encountered, so should not check parent tree.
				break;
			}
		}
		return DataTreeLookup.newLookup(key, false, null);
	}

	/**
	 * Converts this tree's representation to be a complete tree, not a delta.
	 * This disconnects this tree from its parents.
	 * The parent trees are unaffected.
	 */
	public void makeComplete() {
		AbstractDataTreeNode assembled = getRootNode();
		DeltaDataTree myParent = getParent();
		while (myParent != null) {
			assembled = myParent.getRootNode().assembleWith(assembled);
			myParent = myParent.getParent();
		}
		setRootNode(assembled);
		setParent(null);
	}

	/**
	 * Returns a complete node containing the contents of the subtree
	 * rooted at <code>key</code> in the receiver.  Uses the public API.
	 *
	 * @param key
	 *	key of subtree whose contents we want to copy.
	 */
	protected AbstractDataTreeNode naiveCopyCompleteSubtree(IPath key) {
		String[] childNames = getNamesOfChildren(key);
		int numChildren = childNames.length;
		AbstractDataTreeNode[] childNodes;
		if (numChildren == 0) {
			childNodes = AbstractDataTreeNode.NO_CHILDREN;
		} else {
			childNodes = new AbstractDataTreeNode[numChildren];
			/* do for each child */
			for (int i = numChildren; --i >= 0;) {
				childNodes[i] = copyCompleteSubtree(key.append(childNames[i]));
			}
		}
		return new DataTreeNode(key.lastSegment(), getData(key), childNodes);
	}

	/**
	 * Returns a new tree which represents an empty, mutable delta on the
	 * receiver.  It is not possible to obtain a new delta tree if the receiver is
	 * not immutable, as subsequent changes to the receiver would affect the
	 * resulting delta.
	 */
	public DeltaDataTree newEmptyDeltaTree() {
		if (!isImmutable())
			throw new IllegalArgumentException(Messages.dtree_notImmutable);
		DeltaDataTree newTree = (DeltaDataTree) this.copy();
		newTree.setParent(this);
		newTree.emptyDelta();
		return newTree;
	}

	/**
	 * Makes the receiver the root tree in the list of trees on which it is based.
	 * The receiver's representation becomes a complete tree, while its parents'
	 * representations become backward deltas based on the receiver.
	 * It is not possible to re-root a source tree that is not immutable, as this
	 * would require that its parents be expressed as deltas on a source tree
	 * which could still change.
	 *
	 * @exception RuntimeException
	 *	receiver is not immutable
	 */
	public DeltaDataTree reroot() {
		/* self mutex critical region */
		reroot(this);
		return this;
	}

	/**
	 * Makes the given source tree the root tree in the list of trees on which it is based.
	 * The source tree's representation becomes a complete tree, while its parents'
	 * representations become backward deltas based on the source tree.
	 * It is not possible to re-root a source tree that is not immutable, as this
	 * would require that its parents be expressed as deltas on a source tree
	 * which could still change.
	 *
	 * @param sourceTree
	 *	source tree to set as the new root
	 * @exception RuntimeException
	 *	sourceTree is not immutable
	 */
	protected void reroot(DeltaDataTree sourceTree) {
		if (!sourceTree.isImmutable())
			handleImmutableTree();
		DeltaDataTree sourceParent = sourceTree.getParent();
		if (sourceParent == null)
			return;
		this.reroot(sourceParent);
		DeltaDataTree backwardDelta = sourceTree.asBackwardDelta();
		DeltaDataTree complete = sourceParent.assembleWithForwardDelta(sourceTree);
		sourceTree.setRootNode(complete.getRootNode());
		sourceTree.setParent(null);
		sourceParent.setRootNode(backwardDelta.getRootNode());
		sourceParent.setParent(sourceTree);
	}

	/**
	 * Returns a complete node containing the contents of a subtree of the tree.
	 * Returns null  if the node at this key does not exist.  This is a thread-safe
	 * version of copyCompleteSubtree
	 *
	 * @param key key of subtree to copy
	 */
	public AbstractDataTreeNode safeCopyCompleteSubtree(IPath key) {
		AbstractDataTreeNode node = searchNodeAt(key);
		if (node == null)
			return null;
		if (node.isDelta())
			return safeNaiveCopyCompleteSubtree(key);
		//copy the node in case the user wants to hammer the subtree name
		return node.copy();
	}

	/**
	 * Returns a complete node containing the contents of the subtree
	 * rooted at @key in the receiver.  Returns null if this node does not exist in
	 * the tree.  This is a thread-safe version of naiveCopyCompleteSubtree
	 *
	 * @param key
	 *	key of subtree whose contents we want to copy.
	 */
	protected AbstractDataTreeNode safeNaiveCopyCompleteSubtree(IPath key) {
		try {
			String[] childNames = getNamesOfChildren(key);
			int numChildren = childNames.length;
			AbstractDataTreeNode[] childNodes;
			if (numChildren == 0) {
				childNodes = AbstractDataTreeNode.NO_CHILDREN;
			} else {
				childNodes = new AbstractDataTreeNode[numChildren];
				/* do for each child */
				int actualChildCount = 0;
				for (int i = numChildren; --i >= 0;) {
					childNodes[i] = safeCopyCompleteSubtree(key.append(childNames[i]));
					if (childNodes[i] != null)
						actualChildCount++;
				}
				//if there are less actual children due to concurrent deletion, shrink the child array
				if (actualChildCount < numChildren) {
					AbstractDataTreeNode[] actualChildNodes = new AbstractDataTreeNode[actualChildCount];
					for (int iOld = 0, iNew = 0; iOld < numChildren; iOld++)
						if (childNodes[iOld] != null)
							actualChildNodes[iNew++] = childNodes[iOld];
					childNodes = actualChildNodes;
				}
			}
			return new DataTreeNode(key.lastSegment(), getData(key), childNodes);
		} catch (ObjectNotFoundException e) {
			return null;
		}
	}

	/**
	 * Returns the specified node.  Search in the parent if necessary.  Return null
	 * if the node is not found or if it has been deleted
	 */
	protected AbstractDataTreeNode searchNodeAt(IPath key) {
		int keyLength = key.segmentCount();
		for (DeltaDataTree tree = this; tree != null; tree = tree.parent) {
			AbstractDataTreeNode node = tree.rootNode;
			boolean complete = !node.isDelta();
			for (int i = 0; i < keyLength; i++) {
				node = node.childAtOrNull(key.segment(i));
				if (node == null) {
					break;
				}
				if (!node.isDelta()) {
					complete = true;
				}
			}
			if (node != null) {
				if (node.isDeleted())
					break;
				return node;
			}
			if (complete) {
				// Not found, but complete node encountered, so should not check parent tree.
				break;
			}
		}
		return null;
	}

	/**
	 * @see AbstractDataTree#setData(IPath, Object)
	 */
	@Override
	public void setData(IPath key, Object data) {
		if (isImmutable())
			handleImmutableTree();
		if (!includes(key))
			handleNotFound(key);
		assembleNode(key, new DataDeltaNode(key.lastSegment(), data));
	}

	/**
	 * Sets the parent of the tree.
	 */
	protected void setParent(DeltaDataTree aTree) {
		parent = aTree;
	}

	/**
	 * Sets the root node of the tree
	 */
	@Override
	void setRootNode(AbstractDataTreeNode aNode) {
		rootNode = aNode;
	}

	/**
	 * Simplifies the receiver:
	 *	- replaces any DataDelta nodes with the same data as the parent
	 *	  with a NoDataDelta node
	 *	- removes any empty (leaf NoDataDelta) nodes
	 */
	protected void simplify(IComparator comparer) {
		if (parent == null)
			return;
		setRootNode(rootNode.simplifyWithParent(rootKey(), parent, comparer));
	}

	/**
	 * @see org.eclipse.core.internal.utils.IStringPoolParticipant#shareStrings(StringPool)
	 */
	public void storeStrings(StringPool set) {
		AbstractDataTreeNode root = null;
		for (DeltaDataTree dad = this; dad != null; dad = dad.getParent()) {
			root = dad.getRootNode();
			if (root != null)
				root.storeStrings(set);
		}
	}
}
