Copyright (c) 2000, 2006 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
/******************************************************************************* * Copyright (c) 2000, 2006 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.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.osgi.util.NLS;
Data trees can be viewed as generic multi-leaf trees. The tree points to a single rootNode, and each node can contain an arbitrary number of children.

Internally, data trees can be either complete trees (DataTree class), or delta trees (DeltaDataTree class). A DataTree is a stand-alone tree that contains all its own data. A DeltaDataTree only stores the differences between itself and its parent tree. This sparse representation allows the API user to retain chains of delta trees that represent incremental changes to a system. Using the delta trees, the user can undo changes to a tree by going up to the parent tree.

Both representations of the tree support the same API, so the user of a tree never needs to know if they're dealing with a complete tree or a chain of deltas. Delta trees support an extended API of delta operations. See the DeltaDataTree class for details.

See Also:
/** * Data trees can be viewed as generic multi-leaf trees. The tree points to a single * rootNode, and each node can contain an arbitrary number of children. * * <p>Internally, data trees can be either complete trees (DataTree class), or delta * trees (<code>DeltaDataTree</code> class). A DataTree is a stand-alone tree * that contains all its own data. A <code>DeltaDataTree</code> only stores the * differences between itself and its parent tree. This sparse representation allows * the API user to retain chains of delta trees that represent incremental changes to * a system. Using the delta trees, the user can undo changes to a tree by going up to * the parent tree. * * <p>Both representations of the tree support the same API, so the user of a tree * never needs to know if they're dealing with a complete tree or a chain of deltas. * Delta trees support an extended API of delta operations. See the <code>DeltaDataTree * </code> class for details. * * @see DataTree * @see DeltaDataTree */
public abstract class AbstractDataTree {
Whether modifications to the given source tree are allowed
/** * Whether modifications to the given source tree are allowed */
private boolean immutable = false;
Singleton indicating no children
/** * Singleton indicating no children */
protected static final IPath[] NO_CHILDREN = new IPath[0];
Creates a new empty tree
/** * Creates a new empty tree */
public AbstractDataTree() { this.empty(); }
Returns a copy of the receiver, which shares the receiver's instance variables.
/** * Returns a copy of the receiver, which shares the receiver's * instance variables. */
protected AbstractDataTree copy() { AbstractDataTree newTree = this.createInstance(); newTree.setImmutable(this.isImmutable()); newTree.setRootNode(this.getRootNode()); return newTree; }
Returns a copy of the node subtree rooted at the given key.
/** * Returns a copy of the node subtree rooted at the given key. * */
public abstract AbstractDataTreeNode copyCompleteSubtree(IPath key);
Creates a new child in the tree. If a child with such a name exists, it is replaced with the new child
Params:
  • parentKey – key of parent for new child.
  • localName – name for new child.
Throws:
/** * Creates a new child in the tree. If a child with such a name exists, * it is replaced with the new child * * @param parentKey key of parent for new child. * @param localName name for new child. * @exception ObjectNotFoundException * parentKey does not exist in the receiver * @exception RuntimeException * receiver is immutable */
public abstract void createChild(IPath parentKey, String localName);
Creates a new child in the tree. If a child with such a name exists, it is replaced with the new child
Params:
  • parentKey – key of parent for new child.
  • localName – name for new child.
  • object – the data for the new child
Throws:
/** * Creates a new child in the tree. If a child with such a name exists, * it is replaced with the new child * * @param parentKey key of parent for new child. * @param localName name for new child. * @param object the data for the new child * @exception ObjectNotFoundException * parentKey does not exist in the receiver * @exception RuntimeException * receiver is immutable */
public abstract void createChild(IPath parentKey, String localName, Object object);
Creates and returns a new instance of the tree. This is an implementation of the factory method creational pattern for allowing abstract methods to create instances.
Returns:the new tree.
/** * Creates and returns a new instance of the tree. This is an * implementation of the factory method creational pattern for allowing * abstract methods to create instances. * * @return the new tree. */
protected abstract AbstractDataTree createInstance();
Creates or replaces a subtree in the tree. The parent node must exist.
Params:
  • key – key of parent of subtree to create/replace
  • subtree – new subtree to add to tree
Throws:
/** * Creates or replaces a subtree in the tree. The parent node must exist. * * @param key key of parent of subtree to create/replace * @param subtree new subtree to add to tree * @exception RuntimeException receiver is immutable */
public abstract void createSubtree(IPath key, AbstractDataTreeNode subtree);
Deletes a child from the tree.

Note: this method requires both parentKey and localName, making it impossible to delete the root node.

Params:
  • parentKey – parent of node to delete.
  • localName – name of node to delete.
Throws:
/** * Deletes a child from the tree. * * <p>Note: this method requires both parentKey and localName, * making it impossible to delete the root node. * * @param parentKey parent of node to delete. * @param localName name of node to delete. * @exception ObjectNotFoundException * a child of parentKey with name localName does not exist in the receiver * @exception RuntimeException * receiver is immutable */
public abstract void deleteChild(IPath parentKey, String localName);
Initializes the receiver so that it is a complete, empty tree. The result does not represent a delta on another tree. An empty tree is defined to have a root node with null data and no children.
/** * Initializes the receiver so that it is a complete, empty tree. The * result does not represent a delta on another tree. An empty tree is * defined to have a root node with null data and no children. */
public abstract void empty();
Returns the key of a node in the tree.
Params:
  • parentKey – parent of child to retrieve.
  • index – index of the child to retrieve in its parent.
Throws:
/** * Returns the key of a node in the tree. * * @param parentKey * parent of child to retrieve. * @param index * index of the child to retrieve in its parent. * @exception ObjectNotFoundException * parentKey does not exist in the receiver * @exception ArrayIndexOutOfBoundsException * if no child with the given index (runtime exception) */
public IPath getChild(IPath parentKey, int index) { /* Get name of given child of the parent */ String child = getNameOfChild(parentKey, index); return parentKey.append(child); }
Returns the number of children of a node
Params:
  • parentKey – key of the node for which we want to retreive the number of children
Throws:
/** * Returns the number of children of a node * * @param parentKey * key of the node for which we want to retreive the number of children * @exception ObjectNotFoundException * parentKey does not exist in the receiver */
public int getChildCount(IPath parentKey) { return getNamesOfChildren(parentKey).length; }
Returns the keys of all children of a node.
Params:
  • parentKey – key of parent whose children we want to retrieve.
Throws:
/** * Returns the keys of all children of a node. * * @param parentKey * key of parent whose children we want to retrieve. * @exception ObjectNotFoundException * parentKey does not exist in the receiver */
public IPath[] getChildren(IPath parentKey) { String names[] = getNamesOfChildren(parentKey); int len = names.length; if (len == 0) return NO_CHILDREN; IPath answer[] = new IPath[len]; for (int i = 0; i < len; i++) { answer[i] = parentKey.append(names[i]); } return answer; }
Returns the data of a node.
Params:
  • key – key of node for which we want to retrieve data.
Throws:
/** * Returns the data of a node. * * @param key * key of node for which we want to retrieve data. * @exception ObjectNotFoundException * key does not exist in the receiver */
public abstract Object getData(IPath key);
Returns the local name of a node in the tree
Params:
  • parentKey – parent of node whose name we want to retrieve
  • index – index of node in its parent
Throws:
/** * Returns the local name of a node in the tree * * @param parentKey * parent of node whose name we want to retrieve * @param index * index of node in its parent * @exception ObjectNotFoundException * parentKey does not exist in the receiver * @exception ArrayIndexOutOfBoundsException * if no child with the given index */
public String getNameOfChild(IPath parentKey, int index) { String childNames[] = getNamesOfChildren(parentKey); /* Return the requested child as long as its in range */ return childNames[index]; }
Returns the local names for the children of a node
Params:
  • parentKey – key of node whose children we want to retrieve
Throws:
/** * Returns the local names for the children of a node * * @param parentKey * key of node whose children we want to retrieve * @exception ObjectNotFoundException * parentKey does not exist in the receiver */
public abstract String[] getNamesOfChildren(IPath parentKey);
Returns the root node of the tree.

Both subclasses must be able to return their root node. However subclasses can have different types of root nodes, so this is not enforced as an abstract method

/** * Returns the root node of the tree. * * <p>Both subclasses must be able to return their root node. However subclasses * can have different types of root nodes, so this is not enforced as an abstract * method */
AbstractDataTreeNode getRootNode() { throw new AbstractMethodError(Messages.dtree_subclassImplement); }
Handles the case where an attempt was made to modify the tree when it was in an immutable state. Throws an unchecked exception.
/** * Handles the case where an attempt was made to modify * the tree when it was in an immutable state. Throws * an unchecked exception. */
static void handleImmutableTree() { throw new RuntimeException(Messages.dtree_immutable); }
Handles the case where an attempt was made to manipulate an element in the tree that does not exist. Throws an unchecked exception.
/** * Handles the case where an attempt was made to manipulate * an element in the tree that does not exist. Throws an * unchecked exception. */
static void handleNotFound(IPath key) { throw new ObjectNotFoundException(NLS.bind(Messages.dtree_notFound, key)); }
Makes the tree immutable
/** * Makes the tree immutable */
public void immutable() { immutable = true; }
Returns true if the receiver includes a node with the given key, false otherwise.
Params:
  • key – key of node to find
/** * Returns true if the receiver includes a node with the given key, false * otherwise. * * @param key * key of node to find */
public abstract boolean includes(IPath key);
Returns true if the tree is immutable, and false otherwise.
/** * Returns true if the tree is immutable, and false otherwise. */
public boolean isImmutable() { return immutable; }
Returns an object containing: - a flag indicating whether the specified node was found - the data for the node, if it was found
Params:
  • key – key of node for which we want to retrieve data.
/** * Returns an object containing: * - 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. */
public abstract DataTreeLookup lookup(IPath key);
Returns the key of the root node.
/** * Returns the key of the root node. */
public IPath rootKey() { return Path.ROOT; }
Sets the data of a node.
Params:
  • key – key of node for which to set data
  • data – new data value for node
Throws:
/** * Sets the data of a node. * * @param key * key of node for which to set data * @param data * new data value for node * @exception ObjectNotFoundException * the nodeKey does not exist in the receiver * @exception IllegalArgumentException * receiver is immutable */
public abstract void setData(IPath key, Object data);
Sets the immutable field.
/** * Sets the immutable field. */
void setImmutable(boolean bool) { immutable = bool; }
Sets the root node of the tree.

Both subclasses must be able to set their root node. However subclasses can have different types of root nodes, so this is not enforced as an abstract method

/** * Sets the root node of the tree. * * <p>Both subclasses must be able to set their root node. However subclasses * can have different types of root nodes, so this is not enforced as an abstract * method */
void setRootNode(AbstractDataTreeNode node) { throw new Error(Messages.dtree_subclassImplement); } }