- /*
- * @(#)TreePath.java 1.29 03/12/19
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
-
- package javax.swing.tree;
-
- import java.io.*;
- import java.util.Vector;
-
- /**
- * Represents a path to a node. A TreePath is an array of Objects that are
- * vended from a TreeModel. The elements of the array are ordered such
- * that the root is always the first element (index 0) of the array.
- * TreePath is Serializable, but if any
- * components of the path are not serializable, it will not be written
- * out.
- * <p>
- * For further information and examples of using tree paths,
- * see <a
- href="http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html">How to Use Trees</a>
- * in <em>The Java Tutorial.</em>
- * <p>
- * <strong>Warning:</strong>
- * Serialized objects of this class will not be compatible with
- * future Swing releases. The current serialization support is
- * appropriate for short term storage or RMI between applications running
- * the same version of Swing. As of 1.4, support for long term storage
- * of all JavaBeans<sup><font size="-2">TM</font></sup>
- * has been added to the <code>java.beans</code> package.
- * Please see {@link java.beans.XMLEncoder}.
- *
- * @version 1.29 12/19/03
- * @author Scott Violet
- * @author Philip Milne
- */
- public class TreePath extends Object implements Serializable {
- /** Path representing the parent, null if lastPathComponent represents
- * the root. */
- private TreePath parentPath;
- /** Last path component. */
- transient private Object lastPathComponent;
-
- /**
- * Constructs a path from an array of Objects, uniquely identifying
- * the path from the root of the tree to a specific node, as returned
- * by the tree's data model.
- * <p>
- * The model is free to return an array of any Objects it needs to
- * represent the path. The DefaultTreeModel returns an array of
- * TreeNode objects. The first TreeNode in the path is the root of the
- * tree, the last TreeNode is the node identified by the path.
- *
- * @param path an array of Objects representing the path to a node
- */
- public TreePath(Object[] path) {
- if(path == null || path.length == 0)
- throw new IllegalArgumentException("path in TreePath must be non null and not empty.");
- lastPathComponent = path[path.length - 1];
- if(path.length > 1)
- parentPath = new TreePath(path, path.length - 1);
- }
-
- /**
- * Constructs a TreePath containing only a single element. This is
- * usually used to construct a TreePath for the the root of the TreeModel.
- * <p>
- * @param singlePath an Object representing the path to a node
- * @see #TreePath(Object[])
- */
- public TreePath(Object singlePath) {
- if(singlePath == null)
- throw new IllegalArgumentException("path in TreePath must be non null.");
- lastPathComponent = singlePath;
- parentPath = null;
- }
-
- /**
- * Constructs a new TreePath, which is the path identified by
- * <code>parent</code> ending in <code>lastElement</code>.
- */
- protected TreePath(TreePath parent, Object lastElement) {
- if(lastElement == null)
- throw new IllegalArgumentException("path in TreePath must be non null.");
- parentPath = parent;
- lastPathComponent = lastElement;
- }
-
- /**
- * Constructs a new TreePath with the identified path components of
- * length <code>length</code>.
- */
- protected TreePath(Object[] path, int length) {
- lastPathComponent = path[length - 1];
- if(length > 1)
- parentPath = new TreePath(path, length - 1);
- }
-
- /**
- * Primarily provided for subclasses
- * that represent paths in a different manner.
- * If a subclass uses this constructor, it should also override
- * the <code>getPath</code>,
- * <code>getPathCount</code>, and
- * <code>getPathComponent</code> methods,
- * and possibly the <code>equals</code> method.
- */
- protected TreePath() {
- }
-
- /**
- * Returns an ordered array of Objects containing the components of this
- * TreePath. The first element (index 0) is the root.
- *
- * @return an array of Objects representing the TreePath
- * @see #TreePath(Object[])
- */
- public Object[] getPath() {
- int i = getPathCount();
- Object[] result = new Object[i--];
-
- for(TreePath path = this; path != null; path = path.parentPath) {
- result[i--] = path.lastPathComponent;
- }
- return result;
- }
-
- /**
- * Returns the last component of this path. For a path returned by
- * DefaultTreeModel this will return an instance of TreeNode.
- *
- * @return the Object at the end of the path
- * @see #TreePath(Object[])
- */
- public Object getLastPathComponent() {
- return lastPathComponent;
- }
-
- /**
- * Returns the number of elements in the path.
- *
- * @return an int giving a count of items the path
- */
- public int getPathCount() {
- int result = 0;
- for(TreePath path = this; path != null; path = path.parentPath) {
- result++;
- }
- return result;
- }
-
- /**
- * Returns the path component at the specified index.
- *
- * @param element an int specifying an element in the path, where
- * 0 is the first element in the path
- * @return the Object at that index location
- * @throws IllegalArgumentException if the index is beyond the length
- * of the path
- * @see #TreePath(Object[])
- */
- public Object getPathComponent(int element) {
- int pathLength = getPathCount();
-
- if(element < 0 || element >= pathLength)
- throw new IllegalArgumentException("Index " + element + " is out of the specified range");
-
- TreePath path = this;
-
- for(int i = pathLength-1; i != element; i--) {
- path = path.parentPath;
- }
- return path.lastPathComponent;
- }
-
- /**
- * Tests two TreePaths for equality by checking each element of the
- * paths for equality. Two paths are considered equal if they are of
- * the same length, and contain
- * the same elements (<code>.equals</code>).
- *
- * @param o the Object to compare
- */
- public boolean equals(Object o) {
- if(o == this)
- return true;
- if(o instanceof TreePath) {
- TreePath oTreePath = (TreePath)o;
-
- if(getPathCount() != oTreePath.getPathCount())
- return false;
- for(TreePath path = this; path != null; path = path.parentPath) {
- if (!(path.lastPathComponent.equals
- (oTreePath.lastPathComponent))) {
- return false;
- }
- oTreePath = oTreePath.parentPath;
- }
- return true;
- }
- return false;
- }
-
- /**
- * Returns the hashCode for the object. The hash code of a TreePath
- * is defined to be the hash code of the last component in the path.
- *
- * @return the hashCode for the object
- */
- public int hashCode() {
- return lastPathComponent.hashCode();
- }
-
- /**
- * Returns true if <code>aTreePath</code> is a
- * descendant of this
- * TreePath. A TreePath P1 is a descendent of a TreePath P2
- * if P1 contains all of the components that make up
- * P2's path.
- * For example, if this object has the path [a, b],
- * and <code>aTreePath</code> has the path [a, b, c],
- * then <code>aTreePath</code> is a descendant of this object.
- * However, if <code>aTreePath</code> has the path [a],
- * then it is not a descendant of this object.
- *
- * @return true if <code>aTreePath</code> is a descendant of this path
- */
- public boolean isDescendant(TreePath aTreePath) {
- if(aTreePath == this)
- return true;
-
- if(aTreePath != null) {
- int pathLength = getPathCount();
- int oPathLength = aTreePath.getPathCount();
-
- if(oPathLength < pathLength)
- // Can't be a descendant, has fewer components in the path.
- return false;
- while(oPathLength-- > pathLength)
- aTreePath = aTreePath.getParentPath();
- return equals(aTreePath);
- }
- return false;
- }
-
- /**
- * Returns a new path containing all the elements of this object
- * plus <code>child</code>. <code>child</code> will be the last element
- * of the newly created TreePath.
- * This will throw a NullPointerException
- * if child is null.
- */
- public TreePath pathByAddingChild(Object child) {
- if(child == null)
- throw new NullPointerException("Null child not allowed");
-
- return new TreePath(this, child);
- }
-
- /**
- * Returns a path containing all the elements of this object, except
- * the last path component.
- */
- public TreePath getParentPath() {
- return parentPath;
- }
-
- /**
- * Returns a string that displays and identifies this
- * object's properties.
- *
- * @return a String representation of this object
- */
- public String toString() {
- StringBuffer tempSpot = new StringBuffer("[");
-
- for(int counter = 0, maxCounter = getPathCount();counter < maxCounter;
- counter++) {
- if(counter > 0)
- tempSpot.append(", ");
- tempSpot.append(getPathComponent(counter));
- }
- tempSpot.append("]");
- return tempSpot.toString();
- }
-
- // Serialization support.
- private void writeObject(ObjectOutputStream s) throws IOException {
- s.defaultWriteObject();
-
- Vector values = new Vector();
- boolean writePath = true;
-
- if(lastPathComponent != null &&
- (lastPathComponent instanceof Serializable)) {
- values.addElement("lastPathComponent");
- values.addElement(lastPathComponent);
- }
- s.writeObject(values);
- }
-
- private void readObject(ObjectInputStream s)
- throws IOException, ClassNotFoundException {
- s.defaultReadObject();
-
- Vector values = (Vector)s.readObject();
- int indexCounter = 0;
- int maxCounter = values.size();
-
- if(indexCounter < maxCounter && values.elementAt(indexCounter).
- equals("lastPathComponent")) {
- lastPathComponent = values.elementAt(++indexCounter);
- indexCounter++;
- }
- }
- }