1. /*
  2. * @(#)DefaultMutableTreeNode.java 1.12 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.tree;
  8. // ISSUE: this class depends on nothing in AWT -- move to java.util?
  9. import java.io.*;
  10. import java.util.*;
  11. /**
  12. * A <code>DefaultMutableTreeNode</code> is a general-purpose node in a tree data
  13. * structure. A tree node may have at most one parent and 0 or more children.
  14. * <code>DefaultMutableTreeNode</code> provides operations for examining and modifying a
  15. * node's parent and children and also operations for examining the tree that
  16. * the node is a part of. A node's tree is the set of all nodes that can be
  17. * reached by starting at the node and following all the possible links to
  18. * parents and children. A node with no parent is the root of its tree; a
  19. * node with no children is a leaf. A tree may consist of many subtrees,
  20. * each node acting as the root for its own subtree.
  21. * <p>
  22. * This class provides enumerations for efficiently traversing a tree or
  23. * subtree in various orders or for following the path between two nodes.
  24. * A <code>DefaultMutableTreeNode</code> may also hold a reference to a user object, the
  25. * use of which is left to the user. Asking a <code>DefaultMutableTreeNode</code> for its
  26. * string representation with <code>toString()</code> returns the string
  27. * representation of its user object.
  28. * <p>
  29. * <b>This is not a thread safe class.</b>If you intend to use
  30. * a DefaultMutableTreeNode (or a tree of TreeNodes) in more than one thread, you
  31. * need to do your own synchronizing. A good convention to adopt is
  32. * synchronizing on the root node of a tree.
  33. * <p>
  34. * While DefaultMutableTreeNode implements the MutableTreeNode interface and
  35. * will allow you to add in any implementation of MutableTreeNode not all
  36. * of the methods in DefaultMutableTreeNode will be applicable to all
  37. * MutableTreeNodes implementations. Especially with some of the enumerations
  38. * that are provided, using some of these methods assumes the
  39. * DefaultMutableTreeNode contains only DefaultMutableNode instances. All
  40. * of the TreeNode/MutableTreeNode methods will behave as defined no
  41. * matter what implementations are added.
  42. * <p>
  43. * <strong>Warning:</strong>
  44. * Serialized objects of this class will not be compatible with
  45. * future Swing releases. The current serialization support is appropriate
  46. * for short term storage or RMI between applications running the same
  47. * version of Swing. A future release of Swing will provide support for
  48. * long term persistence.
  49. *
  50. * @see MutableTreeNode
  51. *
  52. * @version 1.12 11/29/01
  53. * @author Rob Davis
  54. */
  55. public class DefaultMutableTreeNode extends Object implements Cloneable,
  56. MutableTreeNode, Serializable
  57. {
  58. /**
  59. * An enumeration that is always empty. This is used when an enumeration
  60. * of a leaf node's children is requested.
  61. */
  62. static public final Enumeration EMPTY_ENUMERATION
  63. = new Enumeration() {
  64. public boolean hasMoreElements() { return false; }
  65. public Object nextElement() {
  66. throw new NoSuchElementException("No more elements");
  67. }
  68. };
  69. /** this node's parent, or null if this node has no parent */
  70. protected MutableTreeNode parent;
  71. /** array of children, may be null if this node has no children */
  72. protected Vector children;
  73. /** optional user object */
  74. transient protected Object userObject;
  75. /** true if the node is able to have children */
  76. protected boolean allowsChildren;
  77. /**
  78. * Creates a tree node that has no parent and no children, but which
  79. * allows children.
  80. */
  81. public DefaultMutableTreeNode() {
  82. this(null);
  83. }
  84. /**
  85. * Creates a tree node with no parent, no children, but which allows
  86. * children, and initializes it with the specified user object.
  87. *
  88. * @param userObject an Object provided by the user that constitutes
  89. * the node's data
  90. */
  91. public DefaultMutableTreeNode(Object userObject) {
  92. this(userObject, true);
  93. }
  94. /**
  95. * Creates a tree node with no parent, no children, initialized with
  96. * the specified user object, and that allows children only if
  97. * specified.
  98. *
  99. * @param userObject an Object provided by the user that constitutes
  100. * the node's data
  101. * @param allowsChildren if true, the node is allowed to have child
  102. * nodes -- otherwise, it is always a leaf node
  103. */
  104. public DefaultMutableTreeNode(Object userObject, boolean allowsChildren) {
  105. super();
  106. parent = null;
  107. this.allowsChildren = allowsChildren;
  108. this.userObject = userObject;
  109. }
  110. //
  111. // Primitives
  112. //
  113. /**
  114. * Removes <code>newChild</code> from its present parent (if it has a
  115. * parent), sets the child's parent to this node, and then adds the child
  116. * to this node's child array at index <code>childIndex</code>.
  117. * <code>newChild</code> must not be null and must not be an ancestor of
  118. * this node.
  119. *
  120. * @param newChild the MutableTreeNode to insert under this node
  121. * @param childIndex the index in this node's child array
  122. * where this node is to be inserted
  123. * @exception ArrayIndexOutOfBoundsException if
  124. * <code>childIndex</code> is out of bounds
  125. * @exception IllegalArgumentException if
  126. * <code>newChild</code> is null or is an
  127. * ancestor of this node
  128. * @exception IllegalStateException if this node does not allow
  129. * children
  130. * @see #isNodeDescendant
  131. */
  132. public void insert(MutableTreeNode newChild, int childIndex) {
  133. if (!allowsChildren) {
  134. throw new IllegalStateException("node does not allow children");
  135. } else if (newChild == null) {
  136. throw new IllegalArgumentException("new child is null");
  137. } else if (isNodeAncestor(newChild)) {
  138. throw new IllegalArgumentException("new child is an ancestor");
  139. }
  140. MutableTreeNode oldParent = (MutableTreeNode)newChild.getParent();
  141. if (oldParent != null) {
  142. oldParent.remove(newChild);
  143. }
  144. newChild.setParent(this);
  145. if (children == null) {
  146. children = new Vector();
  147. }
  148. children.insertElementAt(newChild, childIndex);
  149. }
  150. /**
  151. * Removes the child at the specified index from this node's children
  152. * and sets that node's parent to null. The child node to remove
  153. * must be a <code>MutableTreeNode</code>.
  154. *
  155. * @param childIndex the index in this node's child array
  156. * of the child to remove
  157. * @exception ArrayIndexOutOfBoundsException if
  158. * <code>childIndex</code> is out of bounds
  159. */
  160. public void remove(int childIndex) {
  161. MutableTreeNode child = (MutableTreeNode)getChildAt(childIndex);
  162. children.removeElementAt(childIndex);
  163. child.setParent(null);
  164. }
  165. /**
  166. * Sets this node's parent to <code>newParent</code> but does not
  167. * change the parent's child array. This method is called from
  168. * <code>insert()</code> and <code>remove()</code> to
  169. * reassign a child's parent, it should not be messaged from anywhere
  170. * else.
  171. *
  172. * @param newParent this node's new parent
  173. */
  174. public void setParent(MutableTreeNode newParent) {
  175. parent = newParent;
  176. }
  177. /**
  178. * Returns this node's parent or null if this node has no parent.
  179. *
  180. * @return this node's parent TreeNode, or null if this node has no parent
  181. */
  182. public TreeNode getParent() {
  183. return parent;
  184. }
  185. /**
  186. * Returns the child at the specified index in this node's child array.
  187. *
  188. * @param index an index into this node's child array
  189. * @exception ArrayIndexOutOfBoundsException if <code>index</code>
  190. * is out of bounds
  191. * @return the TreeNode in this node's child array at the specified index
  192. */
  193. public TreeNode getChildAt(int index) {
  194. if (children == null) {
  195. throw new ArrayIndexOutOfBoundsException("node has no children");
  196. }
  197. return (TreeNode)children.elementAt(index);
  198. }
  199. /**
  200. * Returns the number of children of this node.
  201. *
  202. * @return an int giving the number of children of this node
  203. */
  204. public int getChildCount() {
  205. if (children == null) {
  206. return 0;
  207. } else {
  208. return children.size();
  209. }
  210. }
  211. /**
  212. * Returns the index of the specified child in this node's child array.
  213. * If the specified node is not a child of this node, returns
  214. * <code>-1</code>. This method performs a linear search and is O(n)
  215. * where n is the number of children.
  216. *
  217. * @param aChild the TreeNode to search for among this node's children
  218. * @exception IllegalArgumentException if <code>aChild</code>
  219. * is null
  220. * @return an int giving the index of the node in this node's child
  221. * array, or <code>-1</code> if the specified node is a not
  222. * a child of this node
  223. */
  224. public int getIndex(TreeNode aChild) {
  225. if (aChild == null) {
  226. throw new IllegalArgumentException("argument is null");
  227. }
  228. if (!isNodeChild(aChild)) {
  229. return -1;
  230. }
  231. return children.indexOf(aChild); // linear search
  232. }
  233. /**
  234. * Creates and returns a forward-order enumeration of this node's
  235. * children. Modifying this node's child array invalidates any child
  236. * enumerations created before the modification.
  237. *
  238. * @return an Enumeration of this node's children
  239. */
  240. public Enumeration children() {
  241. if (children == null) {
  242. return EMPTY_ENUMERATION;
  243. } else {
  244. return children.elements();
  245. }
  246. }
  247. /**
  248. * Determines whether or not this node is allowed to have children.
  249. * If <code>allows</code> is false, all of this node's children are
  250. * removed.
  251. * <p>
  252. * Note: By default, a node allows children.
  253. *
  254. * @param allows true if this node is allowed to have children
  255. */
  256. public void setAllowsChildren(boolean allows) {
  257. if (allows != allowsChildren) {
  258. allowsChildren = allows;
  259. if (!allowsChildren) {
  260. removeAllChildren();
  261. }
  262. }
  263. }
  264. /**
  265. * Returns true if this node is allowed to have children.
  266. *
  267. * @return true if this node allows children, else false
  268. */
  269. public boolean getAllowsChildren() {
  270. return allowsChildren;
  271. }
  272. /**
  273. * Sets the user object for this node to <code>userObject</code>.
  274. *
  275. * @param userObject the Object that constitutes this node's
  276. * user-specified data
  277. * @see #getUserObject
  278. * @see #toString
  279. */
  280. public void setUserObject(Object userObject) {
  281. this.userObject = userObject;
  282. }
  283. /**
  284. * Returns this node's user object.
  285. *
  286. * @return the Object stored at this node by the user
  287. * @see #setUserObject
  288. * @see #toString
  289. */
  290. public Object getUserObject() {
  291. return userObject;
  292. }
  293. //
  294. // Derived methods
  295. //
  296. /**
  297. * Removes the subtree rooted at this node from the tree, giving this
  298. * node a null parent. Does nothing if this node is the root of its
  299. * tree.
  300. */
  301. public void removeFromParent() {
  302. MutableTreeNode parent = (MutableTreeNode)getParent();
  303. if (parent != null) {
  304. parent.remove(this);
  305. }
  306. }
  307. /**
  308. * Removes <code>aChild</code> from this node's child array, giving it a
  309. * null parent.
  310. *
  311. * @param aChild a child of this node to remove
  312. * @exception IllegalArgumentException if <code>aChild</code>
  313. * is null or is not a child of this node
  314. */
  315. public void remove(MutableTreeNode aChild) {
  316. if (aChild == null) {
  317. throw new IllegalArgumentException("argument is null");
  318. }
  319. if (!isNodeChild(aChild)) {
  320. throw new IllegalArgumentException("argument is not a child");
  321. }
  322. remove(getIndex(aChild)); // linear search
  323. }
  324. /**
  325. * Removes all of this node's children, setting their parents to null.
  326. * If this node has no children, this method does nothing.
  327. */
  328. public void removeAllChildren() {
  329. for (int i = getChildCount()-1; i >= 0; i--) {
  330. remove(i);
  331. }
  332. }
  333. /**
  334. * Removes <code>newChild</code> from its parent and makes it a child of
  335. * this node by adding it to the end of this node's child array.
  336. *
  337. * @see #insert
  338. * @param newChild node to add as a child of this node
  339. * @exception IllegalArgumentException if <code>newChild</code>
  340. * is null
  341. * @exception IllegalStateException if this node does not allow
  342. * children
  343. */
  344. public void add(MutableTreeNode newChild) {
  345. if(newChild != null && newChild.getParent() == this)
  346. insert(newChild, getChildCount() - 1);
  347. else
  348. insert(newChild, getChildCount());
  349. }
  350. //
  351. // Tree Queries
  352. //
  353. /**
  354. * Returns true if <code>anotherNode</code> is an ancestor of this node
  355. * -- if it is this node, this node's parent, or an ancestor of this
  356. * node's parent. (Note that a node is considered an ancestor of itself.)
  357. * If <code>anotherNode</code> is null, this method returns false. This
  358. * operation is at worst O(h) where h is the distance from the root to
  359. * this node.
  360. *
  361. * @see #isNodeDescendant
  362. * @see #getSharedAncestor
  363. * @param anotherNode node to test as an ancestor of this node
  364. * @return true if this node is a descendant of <code>anotherNode</code>
  365. */
  366. public boolean isNodeAncestor(TreeNode anotherNode) {
  367. if (anotherNode == null) {
  368. return false;
  369. }
  370. TreeNode ancestor = this;
  371. do {
  372. if (ancestor == anotherNode) {
  373. return true;
  374. }
  375. } while((ancestor = ancestor.getParent()) != null);
  376. return false;
  377. }
  378. /**
  379. * Returns true if <code>anotherNode</code> is a descendant of this node
  380. * -- if it is this node, one of this node's children, or a descendant of
  381. * one of this node's children. Note that a node is considered a
  382. * descendant of itself. If <code>anotherNode</code> is null, returns
  383. * false. This operation is at worst O(h) where h is the distance from the
  384. * root to <code>anotherNode</code>.
  385. *
  386. * @see #isNodeAncestor
  387. * @see #getSharedAncestor
  388. * @param anotherNode node to test as descendant of this node
  389. * @return true if this node is an ancestor of <code>anotherNode</code>
  390. */
  391. public boolean isNodeDescendant(DefaultMutableTreeNode anotherNode) {
  392. if (anotherNode == null)
  393. return false;
  394. return anotherNode.isNodeAncestor(this);
  395. }
  396. /**
  397. * Returns the nearest common ancestor to this node and <code>aNode</code>.
  398. * Returns null, if no such ancestor exists -- if this node and
  399. * <code>aNode</code> are in different trees or if <code>aNode</code> is
  400. * null. A node is considered an ancestor of itself.
  401. *
  402. * @see #isNodeAncestor
  403. * @see #isNodeDescendant
  404. * @param aNode node to find common ancestor with
  405. * @return nearest ancestor common to this node and <code>aNode</code>,
  406. * or null if none
  407. */
  408. public TreeNode getSharedAncestor(DefaultMutableTreeNode aNode) {
  409. if (aNode == this) {
  410. return this;
  411. } else if (aNode == null) {
  412. return null;
  413. }
  414. int level1, level2, diff;
  415. TreeNode node1, node2;
  416. level1 = getLevel();
  417. level2 = aNode.getLevel();
  418. if (level2 > level1) {
  419. diff = level2 - level1;
  420. node1 = aNode;
  421. node2 = this;
  422. } else {
  423. diff = level1 - level2;
  424. node1 = this;
  425. node2 = aNode;
  426. }
  427. // Go up the tree until the nodes are at the same level
  428. while (diff > 0) {
  429. node1 = node1.getParent();
  430. diff--;
  431. }
  432. // Move up the tree until we find a common ancestor. Since we know
  433. // that both nodes are at the same level, we won't cross paths
  434. // unknowingly (if there is a common ancestor, both nodes hit it in
  435. // the same iteration).
  436. do {
  437. if (node1 == node2) {
  438. return node1;
  439. }
  440. node1 = node1.getParent();
  441. node2 = node2.getParent();
  442. } while (node1 != null);// only need to check one -- they're at the
  443. // same level so if one is null, the other is
  444. if (node1 != null || node2 != null) {
  445. throw new InternalError ("nodes should be null");
  446. }
  447. return null;
  448. }
  449. /**
  450. * Returns true if and only if <code>aNode</code> is in the same tree
  451. * as this node. Returns false if <code>aNode</code> is null.
  452. *
  453. * @see #getSharedAncestor
  454. * @see #getRoot
  455. * @return true if <code>aNode</code> is in the same tree as this node;
  456. * false if <code>aNode</code> is null
  457. */
  458. public boolean isNodeRelated(DefaultMutableTreeNode aNode) {
  459. return (aNode != null) && (getRoot() == aNode.getRoot());
  460. }
  461. /**
  462. * Returns the depth of the tree rooted at this node -- the longest
  463. * distance from this node to a leaf. If this node has no children,
  464. * returns 0. This operation is much more expensive than
  465. * <code>getLevel()</code> because it must effectively traverse the entire
  466. * tree rooted at this node.
  467. *
  468. * @see #getLevel
  469. * @return the depth of the tree whose root is this node
  470. */
  471. public int getDepth() {
  472. Object last = null;
  473. Enumeration enum = breadthFirstEnumeration();
  474. while (enum.hasMoreElements()) {
  475. last = enum.nextElement();
  476. }
  477. if (last == null) {
  478. throw new InternalError ("nodes should be null");
  479. }
  480. return ((DefaultMutableTreeNode)last).getLevel() - getLevel();
  481. }
  482. /**
  483. * Returns the number of levels above this node -- the distance from
  484. * the root to this node. If this node is the root, returns 0.
  485. *
  486. * @see #getDepth
  487. * @return the number of levels above this node
  488. */
  489. public int getLevel() {
  490. TreeNode ancestor;
  491. int levels = 0;
  492. ancestor = this;
  493. while((ancestor = ancestor.getParent()) != null){
  494. levels++;
  495. }
  496. return levels;
  497. }
  498. /**
  499. * Returns the path from the root, to get to this node. The last
  500. * element in the path is this node.
  501. *
  502. * @return an array of TreeNode objects giving the path, where the
  503. * first element in the path is the root and the last
  504. * element is this node.
  505. */
  506. public TreeNode[] getPath() {
  507. return getPathToRoot(this, 0);
  508. }
  509. /**
  510. * Builds the parents of node up to and including the root node,
  511. * where the original node is the last element in the returned array.
  512. * The length of the returned array gives the node's depth in the
  513. * tree.
  514. *
  515. * @param aNode the TreeNode to get the path for
  516. * @param depth an int giving the number of steps already taken towards
  517. * the root (on recursive calls), used to size the returned array
  518. * @return an array of TreeNodes giving the path from the root to the
  519. * specified node
  520. */
  521. protected TreeNode[] getPathToRoot(TreeNode aNode, int depth) {
  522. TreeNode[] retNodes;
  523. /* Check for null, in case someone passed in a null node, or
  524. they passed in an element that isn't rooted at root. */
  525. if(aNode == null) {
  526. if(depth == 0)
  527. return null;
  528. else
  529. retNodes = new TreeNode[depth];
  530. }
  531. else {
  532. depth++;
  533. retNodes = getPathToRoot(aNode.getParent(), depth);
  534. retNodes[retNodes.length - depth] = aNode;
  535. }
  536. return retNodes;
  537. }
  538. /**
  539. * Returns the user object path, from the root, to get to this node.
  540. * If some of the TreeNodes in the path have null user objects, the
  541. * returned path will contain nulls.
  542. */
  543. public Object[] getUserObjectPath() {
  544. TreeNode[] realPath = getPath();
  545. Object[] retPath = new Object[realPath.length];
  546. for(int counter = 0; counter < realPath.length; counter++)
  547. retPath[counter] = ((DefaultMutableTreeNode)realPath[counter])
  548. .getUserObject();
  549. return retPath;
  550. }
  551. /**
  552. * Returns the root of the tree that contains this node. The root is
  553. * the ancestor with a null parent.
  554. *
  555. * @see #isNodeAncestor
  556. * @return the root of the tree that contains this node
  557. */
  558. public TreeNode getRoot() {
  559. TreeNode ancestor = this;
  560. TreeNode previous;
  561. do {
  562. previous = ancestor;
  563. ancestor = ancestor.getParent();
  564. } while (ancestor != null);
  565. return previous;
  566. }
  567. /**
  568. * Returns true if this node is the root of the tree. The root is
  569. * the only node in the tree with a null parent; every tree has exactly
  570. * one root.
  571. *
  572. * @return true if this node is the root of its tree
  573. */
  574. public boolean isRoot() {
  575. return getParent() == null;
  576. }
  577. /**
  578. * Returns the node that follows this node in a preorder traversal of this
  579. * node's tree. Returns null if this node is the last node of the
  580. * traversal. This is an inefficient way to traverse the entire tree; use
  581. * an enumeration, instead.
  582. *
  583. * @see #preorderEnumeration
  584. * @return the node that follows this node in a preorder traversal, or
  585. * null if this node is last
  586. */
  587. public DefaultMutableTreeNode getNextNode() {
  588. if (getChildCount() == 0) {
  589. // No children, so look for nextSibling
  590. DefaultMutableTreeNode nextSibling = getNextSibling();
  591. if (nextSibling == null) {
  592. DefaultMutableTreeNode aNode = (DefaultMutableTreeNode)getParent();
  593. do {
  594. if (aNode == null) {
  595. return null;
  596. }
  597. nextSibling = aNode.getNextSibling();
  598. if (nextSibling != null) {
  599. return nextSibling;
  600. }
  601. aNode = (DefaultMutableTreeNode)aNode.getParent();
  602. } while(true);
  603. } else {
  604. return nextSibling;
  605. }
  606. } else {
  607. return (DefaultMutableTreeNode)getChildAt(0);
  608. }
  609. }
  610. /**
  611. * Returns the node that precedes this node in a preorder traversal of
  612. * this node's tree. Returns null if this node is the first node of the
  613. * traveral -- the root of the tree. This is an inefficient way to
  614. * traverse the entire tree; use an enumeration, instead.
  615. *
  616. * @see #preorderEnumeration
  617. * @return the node that precedes this node in a preorder traversal, or
  618. * null if this node is the first
  619. */
  620. public DefaultMutableTreeNode getPreviousNode() {
  621. DefaultMutableTreeNode previousSibling;
  622. DefaultMutableTreeNode myParent = (DefaultMutableTreeNode)getParent();
  623. if (myParent == null) {
  624. return null;
  625. }
  626. previousSibling = getPreviousSibling();
  627. if (previousSibling != null) {
  628. if (previousSibling.getChildCount() == 0)
  629. return previousSibling;
  630. else
  631. return previousSibling.getLastLeaf();
  632. } else {
  633. return myParent;
  634. }
  635. }
  636. /**
  637. * Creates and returns an enumeration that traverses the subtree rooted at
  638. * this node in preorder. The first node returned by the enumeration's
  639. * <code>nextElement()</code> method is this node.<P>
  640. *
  641. * Modifying the tree by inserting, removing, or moving a node invalidates
  642. * any enumerations created before the modification.
  643. *
  644. * @see #postorderEnumeration
  645. * @return an enumeration for traversing the tree in preorder
  646. */
  647. public Enumeration preorderEnumeration() {
  648. return new PreorderEnumeration(this);
  649. }
  650. /**
  651. * Creates and returns an enumeration that traverses the subtree rooted at
  652. * this node in postorder. The first node returned by the enumeration's
  653. * <code>nextElement()</code> method is the leftmost leaf. This is the
  654. * same as a depth-first traversal.<P>
  655. *
  656. * Modifying the tree by inserting, removing, or moving a node invalidates
  657. * any enumerations created before the modification.
  658. *
  659. * @see #depthFirstEnumeration
  660. * @see #preorderEnumeration
  661. * @return an enumeration for traversing the tree in postorder
  662. */
  663. public Enumeration postorderEnumeration() {
  664. return new PostorderEnumeration(this);
  665. }
  666. /**
  667. * Creates and returns an enumeration that traverses the subtree rooted at
  668. * this node in breadth-first order. The first node returned by the
  669. * enumeration's <code>nextElement()</code> method is this node.<P>
  670. *
  671. * Modifying the tree by inserting, removing, or moving a node invalidates
  672. * any enumerations created before the modification.
  673. *
  674. * @see #depthFirstEnumeration
  675. * @return an enumeration for traversing the tree in breadth-first order
  676. */
  677. public Enumeration breadthFirstEnumeration() {
  678. return new BreadthFirstEnumeration(this);
  679. }
  680. /**
  681. * Creates and returns an enumeration that traverses the subtree rooted at
  682. * this node in depth-first order. The first node returned by the
  683. * enumeration's <code>nextElement()</code> method is the leftmost leaf.
  684. * This is the same as a postorder traversal.<P>
  685. *
  686. * Modifying the tree by inserting, removing, or moving a node invalidates
  687. * any enumerations created before the modification.
  688. *
  689. * @see #breadthFirstEnumeration
  690. * @see #postorderEnumeration
  691. * @return an enumeration for traversing the tree in depth-first order
  692. */
  693. public Enumeration depthFirstEnumeration() {
  694. return postorderEnumeration();
  695. }
  696. /**
  697. * Creates and returns an enumeration that follows the path from
  698. * <code>ancestor</code> to this node. The enumeration's
  699. * <code>nextElement()</code> method first returns <code>ancestor</code>,
  700. * then the child of <code>ancestor</code> that is an ancestor of this
  701. * node, and so on, and finally returns this node. Creation of the
  702. * enumeration is O(m) where m is the number of nodes between this node
  703. * and <code>ancestor</code>, inclusive. Each <code>nextElement()</code>
  704. * message is O(1).<P>
  705. *
  706. * Modifying the tree by inserting, removing, or moving a node invalidates
  707. * any enumerations created before the modification.
  708. *
  709. * @see #isNodeAncestor
  710. * @see #isNodeDescendant
  711. * @exception IllegalArgumentException if <code>ancestor</code> is
  712. * not an ancestor of this node
  713. * @return an enumeration for following the path from an ancestor of
  714. * this node to this one
  715. */
  716. public Enumeration pathFromAncestorEnumeration(TreeNode ancestor){
  717. return new PathBetweenNodesEnumeration(ancestor, this);
  718. }
  719. //
  720. // Child Queries
  721. //
  722. /**
  723. * Returns true if <code>aNode</code> is a child of this node. If
  724. * <code>aNode</code> is null, this method returns false.
  725. *
  726. * @return true if <code>aNode</code> is a child of this node; false if
  727. * <code>aNode</code> is null
  728. */
  729. public boolean isNodeChild(TreeNode aNode) {
  730. boolean retval;
  731. if (aNode == null) {
  732. retval = false;
  733. } else {
  734. if (getChildCount() == 0) {
  735. retval = false;
  736. } else {
  737. retval = (aNode.getParent() == this);
  738. }
  739. }
  740. return retval;
  741. }
  742. /**
  743. * Returns this node's first child. If this node has no children,
  744. * throws NoSuchElementException.
  745. *
  746. * @return the first child of this node
  747. * @exception NoSuchElementException if this node has no children
  748. */
  749. public TreeNode getFirstChild() {
  750. if (getChildCount() == 0) {
  751. throw new NoSuchElementException("node has no children");
  752. }
  753. return getChildAt(0);
  754. }
  755. /**
  756. * Returns this node's last child. If this node has no children,
  757. * throws NoSuchElementException.
  758. *
  759. * @return the last child of this node
  760. * @exception NoSuchElementException if this node has no children
  761. */
  762. public TreeNode getLastChild() {
  763. if (getChildCount() == 0) {
  764. throw new NoSuchElementException("node has no children");
  765. }
  766. return getChildAt(getChildCount()-1);
  767. }
  768. /**
  769. * Returns the child in this node's child array that immediately
  770. * follows <code>aChild</code>, which must be a child of this node. If
  771. * <code>aChild</code> is the last child, returns null. This method
  772. * performs a linear search of this node's children for
  773. * <code>aChild</code> and is O(n) where n is the number of children; to
  774. * traverse the entire array of children, use an enumeration instead.
  775. *
  776. * @see #children
  777. * @exception IllegalArgumentException if <code>aChild</code> is
  778. * null or is not a child of this node
  779. * @return the child of this node that immediately follows
  780. * <code>aChild</code>
  781. */
  782. public TreeNode getChildAfter(TreeNode aChild) {
  783. if (aChild == null) {
  784. throw new IllegalArgumentException("argument is null");
  785. }
  786. int index = getIndex(aChild); // linear search
  787. if (index == -1) {
  788. throw new IllegalArgumentException("node is not a child");
  789. }
  790. if (index < getChildCount() - 1) {
  791. return getChildAt(index + 1);
  792. } else {
  793. return null;
  794. }
  795. }
  796. /**
  797. * Returns the child in this node's child array that immediately
  798. * precedes <code>aChild</code>, which must be a child of this node. If
  799. * <code>aChild</code> is the first child, returns null. This method
  800. * performs a linear search of this node's children for <code>aChild</code>
  801. * and is O(n) where n is the number of children.
  802. *
  803. * @exception IllegalArgumentException if <code>aChild</code> is null
  804. * or is not a child of this node
  805. * @return the child of this node that immediately precedes
  806. * <code>aChild</code>
  807. */
  808. public TreeNode getChildBefore(TreeNode aChild) {
  809. if (aChild == null) {
  810. throw new IllegalArgumentException("argument is null");
  811. }
  812. int index = getIndex(aChild); // linear search
  813. if (index == -1) {
  814. throw new IllegalArgumentException("argument is not a child");
  815. }
  816. if (index > 0) {
  817. return getChildAt(index - 1);
  818. } else {
  819. return null;
  820. }
  821. }
  822. //
  823. // Sibling Queries
  824. //
  825. /**
  826. * Returns true if <code>anotherNode</code> is a sibling of (has the
  827. * same parent as) this node. A node is its own sibling. If
  828. * <code>anotherNode</code> is null, returns false.
  829. *
  830. * @param anotherNode node to test as sibling of this node
  831. * @return true if <code>anotherNode</code> is a sibling of this node
  832. */
  833. public boolean isNodeSibling(TreeNode anotherNode) {
  834. boolean retval;
  835. if (anotherNode == null) {
  836. retval = false;
  837. } else if (anotherNode == this) {
  838. retval = true;
  839. } else {
  840. TreeNode myParent = getParent();
  841. retval = (myParent != null && myParent == anotherNode.getParent());
  842. if (retval && !((DefaultMutableTreeNode)getParent())
  843. .isNodeChild(anotherNode)) {
  844. throw new InternalError("sibling has different parent");
  845. }
  846. }
  847. return retval;
  848. }
  849. /**
  850. * Returns the number of siblings of this node. A node is its own sibling
  851. * (if it has no parent or no siblings, this method returns
  852. * <code>1</code>).
  853. *
  854. * @return the number of siblings of this node
  855. */
  856. public int getSiblingCount() {
  857. TreeNode myParent = getParent();
  858. if (myParent == null) {
  859. return 1;
  860. } else {
  861. return myParent.getChildCount();
  862. }
  863. }
  864. /**
  865. * Returns the next sibling of this node in the parent's children array.
  866. * Returns null if this node has no parent or is the parent's last child.
  867. * This method performs a linear search that is O(n) where n is the number
  868. * of children; to traverse the entire array, use the parent's child
  869. * enumeration instead.
  870. *
  871. * @see #children
  872. * @return the sibling of this node that immediately follows this node
  873. */
  874. public DefaultMutableTreeNode getNextSibling() {
  875. DefaultMutableTreeNode retval;
  876. DefaultMutableTreeNode myParent = (DefaultMutableTreeNode)getParent();
  877. if (myParent == null) {
  878. retval = null;
  879. } else {
  880. retval = (DefaultMutableTreeNode)myParent.getChildAfter(this); // linear search
  881. }
  882. if (retval != null && !isNodeSibling(retval)) {
  883. throw new InternalError("child of parent is not a sibling");
  884. }
  885. return retval;
  886. }
  887. /**
  888. * Returns the previous sibling of this node in the parent's children
  889. * array. Returns null if this node has no parent or is the parent's
  890. * first child. This method performs a linear search that is O(n) where n
  891. * is the number of children.
  892. *
  893. * @return the sibling of this node that immediately precedes this node
  894. */
  895. public DefaultMutableTreeNode getPreviousSibling() {
  896. DefaultMutableTreeNode retval;
  897. DefaultMutableTreeNode myParent = (DefaultMutableTreeNode)getParent();
  898. if (myParent == null) {
  899. retval = null;
  900. } else {
  901. retval = (DefaultMutableTreeNode)myParent.getChildBefore(this); // linear search
  902. }
  903. if (retval != null && !isNodeSibling(retval)) {
  904. throw new InternalError("child of parent is not a sibling");
  905. }
  906. return retval;
  907. }
  908. //
  909. // Leaf Queries
  910. //
  911. /**
  912. * Returns true if this node has no children. To distinguish between
  913. * nodes that have no children and nodes that <i>cannot</i> have
  914. * children (e.g. to distinguish files from empty directories), use this
  915. * method in conjunction with <code>getAllowsChildren</code>
  916. *
  917. * @see #getAllowsChildren
  918. * @return true if this node has no children
  919. */
  920. public boolean isLeaf() {
  921. return (getChildCount() == 0);
  922. }
  923. /**
  924. * Finds and returns the first leaf that is a descendant of this node --
  925. * either this node or its first child's first leaf.
  926. * Returns this node if it is a leaf.
  927. *
  928. * @see #isLeaf
  929. * @see #isNodeDescendant
  930. * @return the first leaf in the subtree rooted at this node
  931. */
  932. public DefaultMutableTreeNode getFirstLeaf() {
  933. DefaultMutableTreeNode node = this;
  934. while (!node.isLeaf()) {
  935. node = (DefaultMutableTreeNode)node.getFirstChild();
  936. }
  937. return node;
  938. }
  939. /**
  940. * Finds and returns the last leaf that is a descendant of this node --
  941. * either this node or its last child's last leaf.
  942. * Returns this node if it is a leaf.
  943. *
  944. * @see #isLeaf
  945. * @see #isNodeDescendant
  946. * @return the last leaf in the subtree rooted at this node
  947. */
  948. public DefaultMutableTreeNode getLastLeaf() {
  949. DefaultMutableTreeNode node = this;
  950. while (!node.isLeaf()) {
  951. node = (DefaultMutableTreeNode)node.getLastChild();
  952. }
  953. return node;
  954. }
  955. /**
  956. * Returns the leaf after this node or null if this node is the
  957. * last leaf in the tree.
  958. * <p>
  959. * In this implementation of the <code>MutableNode</code> interface,
  960. * this operation is very inefficient. In order to determine the
  961. * next node, this method first performs a linear search in the
  962. * parent's child-list in order to find the current node.
  963. * <p>
  964. * That implementation makes the operation suitable for short
  965. * traversals from a known position. But to traverse all of the
  966. * leaves in the tree, you should use <code>depthFirstEnumeration</code>
  967. * to enumerate the nodes in the tree and use <code>isLeaf</code>
  968. * on each node to determine which are leaves.
  969. *
  970. * @see #depthFirstEnumeration
  971. * @see #isLeaf
  972. * @return returns the next leaf past this node
  973. */
  974. public DefaultMutableTreeNode getNextLeaf() {
  975. DefaultMutableTreeNode nextSibling;
  976. DefaultMutableTreeNode myParent = (DefaultMutableTreeNode)getParent();
  977. if (myParent == null)
  978. return null;
  979. nextSibling = getNextSibling(); // linear search
  980. if (nextSibling != null)
  981. return nextSibling.getFirstLeaf();
  982. return myParent.getNextLeaf(); // tail recursion
  983. }
  984. /**
  985. * Returns the leaf before this node or null if this node is the
  986. * first leaf in the tree.
  987. * <p>
  988. * In this implementation of the <code>MutableNode</code> interface,
  989. * this operation is very inefficient. In order to determine the
  990. * previous node, this method first performs a linear search in the
  991. * parent's child-list in order to find the current node.
  992. * <p>
  993. * That implementation makes the operation suitable for short
  994. * traversals from a known position. But to traverse all of the
  995. * leaves in the tree, you should use <code>depthFirstEnumeration</code>
  996. * to enumerate the nodes in the tree and use <code>isLeaf</code>
  997. * on each node to determine which are leaves.
  998. *
  999. * @see #depthFirstEnumeration
  1000. * @see #isLeaf
  1001. * @return returns the leaf before this node
  1002. */
  1003. public DefaultMutableTreeNode getPreviousLeaf() {
  1004. DefaultMutableTreeNode previousSibling;
  1005. DefaultMutableTreeNode myParent = (DefaultMutableTreeNode)getParent();
  1006. if (myParent == null)
  1007. return null;
  1008. previousSibling = getPreviousSibling(); // linear search
  1009. if (previousSibling != null)
  1010. return previousSibling.getLastLeaf();
  1011. return myParent.getPreviousLeaf(); // tail recursion
  1012. }
  1013. /**
  1014. * Returns the total number of leaves that are descendants of this node.
  1015. * If this node is a leaf, returns <code>1</code>. This method is O(n)
  1016. * where n is the number of descendants of this node.
  1017. *
  1018. * @see #isNodeAncestor
  1019. * @return the number of leaves beneath this node
  1020. */
  1021. public int getLeafCount() {
  1022. int count = 0;
  1023. TreeNode node;
  1024. Enumeration enum = breadthFirstEnumeration(); // order matters not
  1025. while (enum.hasMoreElements()) {
  1026. node = (TreeNode)enum.nextElement();
  1027. if (node.isLeaf()) {
  1028. count++;
  1029. }
  1030. }
  1031. if (count < 1) {
  1032. throw new InternalError("tree has zero leaves");
  1033. }
  1034. return count;
  1035. }
  1036. //
  1037. // Overrides
  1038. //
  1039. /**
  1040. * Returns the result of sending <code>toString()</code> to this node's
  1041. * user object, or null if this node has no user object.
  1042. *
  1043. * @see #getUserObject
  1044. */
  1045. public String toString() {
  1046. if (userObject == null) {
  1047. return null;
  1048. } else {
  1049. return userObject.toString();
  1050. }
  1051. }
  1052. /**
  1053. * Overridden to make clone public. Returns a shallow copy of this node;
  1054. * the new node has no parent or children and has a reference to the same
  1055. * user object, if any.
  1056. *
  1057. * @return a copy of this node
  1058. */
  1059. public Object clone() {
  1060. DefaultMutableTreeNode newNode = null;
  1061. try {
  1062. newNode = (DefaultMutableTreeNode)super.clone();
  1063. // shallow copy -- the new node has no parent or children
  1064. newNode.children = null;
  1065. newNode.parent = null;
  1066. } catch (CloneNotSupportedException e) {
  1067. // Won't happen because we implement Cloneable
  1068. throw new InternalError(e.toString());
  1069. }
  1070. return newNode;
  1071. }
  1072. // Serialization support.
  1073. private void writeObject(ObjectOutputStream s) throws IOException {
  1074. Object[] tValues;
  1075. s.defaultWriteObject();
  1076. // Save the userObject, if its Serializable.
  1077. if(userObject != null && userObject instanceof Serializable) {
  1078. tValues = new Object[2];
  1079. tValues[0] = "userObject";
  1080. tValues[1] = userObject;
  1081. }
  1082. else
  1083. tValues = new Object[0];
  1084. s.writeObject(tValues);
  1085. }
  1086. private void readObject(ObjectInputStream s)
  1087. throws IOException, ClassNotFoundException {
  1088. Object[] tValues;
  1089. s.defaultReadObject();
  1090. tValues = (Object[])s.readObject();
  1091. if(tValues.length > 0 && tValues[0].equals("userObject"))
  1092. userObject = tValues[1];
  1093. }
  1094. final class PreorderEnumeration implements Enumeration {
  1095. protected Stack stack;
  1096. public PreorderEnumeration(TreeNode rootNode) {
  1097. super();
  1098. Vector v = new Vector(1);
  1099. v.addElement(rootNode); // PENDING: don't really need a vector
  1100. stack = new Stack();
  1101. stack.push(v.elements());
  1102. }
  1103. public boolean hasMoreElements() {
  1104. return (!stack.empty() &&
  1105. ((Enumeration)stack.peek()).hasMoreElements());
  1106. }
  1107. public Object nextElement() {
  1108. Enumeration enumer = (Enumeration)stack.peek();
  1109. TreeNode node = (TreeNode)enumer.nextElement();
  1110. Enumeration children = node.children();
  1111. if (!enumer.hasMoreElements()) {
  1112. stack.pop();
  1113. }
  1114. if (children.hasMoreElements()) {
  1115. stack.push(children);
  1116. }
  1117. return node;
  1118. }
  1119. } // End of class PreorderEnumeration
  1120. final class PostorderEnumeration implements Enumeration {
  1121. protected TreeNode root;
  1122. protected Enumeration children;
  1123. protected Enumeration subtree;
  1124. public PostorderEnumeration(TreeNode rootNode) {
  1125. super();
  1126. root = rootNode;
  1127. children = root.children();
  1128. subtree = EMPTY_ENUMERATION;
  1129. }
  1130. public boolean hasMoreElements() {
  1131. return root != null;
  1132. }
  1133. public Object nextElement() {
  1134. Object retval;
  1135. if (subtree.hasMoreElements()) {
  1136. retval = subtree.nextElement();
  1137. } else if (children.hasMoreElements()) {
  1138. subtree = new PostorderEnumeration(
  1139. (TreeNode)children.nextElement());
  1140. retval = subtree.nextElement();
  1141. } else {
  1142. retval = root;
  1143. root = null;
  1144. }
  1145. return retval;
  1146. }
  1147. } // End of class PostorderEnumeration
  1148. final class BreadthFirstEnumeration implements Enumeration {
  1149. protected Queue queue;
  1150. public BreadthFirstEnumeration(TreeNode rootNode) {
  1151. super();
  1152. Vector v = new Vector(1);
  1153. v.addElement(rootNode); // PENDING: don't really need a vector
  1154. queue = new Queue();
  1155. queue.enqueue(v.elements());
  1156. }
  1157. public boolean hasMoreElements() {
  1158. return (!queue.isEmpty() &&
  1159. ((Enumeration)queue.firstObject()).hasMoreElements());
  1160. }
  1161. public Object nextElement() {
  1162. Enumeration enumer = (Enumeration)queue.firstObject();
  1163. TreeNode node = (TreeNode)enumer.nextElement();
  1164. Enumeration children = node.children();
  1165. if (!enumer.hasMoreElements()) {
  1166. queue.dequeue();
  1167. }
  1168. if (children.hasMoreElements()) {
  1169. queue.enqueue(children);
  1170. }
  1171. return node;
  1172. }
  1173. // A simple queue with a linked list data structure.
  1174. final class Queue {
  1175. QNode head; // null if empty
  1176. QNode tail;
  1177. final class QNode {
  1178. public Object object;
  1179. public QNode next; // null if end
  1180. public QNode(Object object, QNode next) {
  1181. this.object = object;
  1182. this.next = next;
  1183. }
  1184. }
  1185. public void enqueue(Object anObject) {
  1186. if (head == null) {
  1187. head = tail = new QNode(anObject, null);
  1188. } else {
  1189. tail.next = new QNode(anObject, null);
  1190. tail = tail.next;
  1191. }
  1192. }
  1193. public Object dequeue() {
  1194. if (head == null) {
  1195. throw new NoSuchElementException("No more elements");
  1196. }
  1197. Object retval = head.object;
  1198. QNode oldHead = head;
  1199. head = head.next;
  1200. if (head == null) {
  1201. tail = null;
  1202. } else {
  1203. oldHead.next = null;
  1204. }
  1205. return retval;
  1206. }
  1207. public Object firstObject() {
  1208. if (head == null) {
  1209. throw new NoSuchElementException("No more elements");
  1210. }
  1211. return head.object;
  1212. }
  1213. public boolean isEmpty() {
  1214. return head == null;
  1215. }
  1216. } // End of class Queue
  1217. } // End of class BreadthFirstEnumeration
  1218. final class PathBetweenNodesEnumeration implements Enumeration {
  1219. protected Stack stack;
  1220. public PathBetweenNodesEnumeration(TreeNode ancestor,
  1221. TreeNode descendant)
  1222. {
  1223. super();
  1224. if (ancestor == null || descendant == null) {
  1225. throw new IllegalArgumentException("argument is null");
  1226. }
  1227. TreeNode current;
  1228. stack = new Stack();
  1229. stack.push(descendant);
  1230. current = descendant;
  1231. while (current != ancestor) {
  1232. current = current.getParent();
  1233. if (current == null && descendant != ancestor) {
  1234. throw new IllegalArgumentException("node " + ancestor +
  1235. " is not an ancestor of " + descendant);
  1236. }
  1237. stack.push(current);
  1238. }
  1239. }
  1240. public boolean hasMoreElements() {
  1241. return stack.size() > 0;
  1242. }
  1243. public Object nextElement() {
  1244. try {
  1245. return stack.pop();
  1246. } catch (EmptyStackException e) {
  1247. throw new NoSuchElementException("No more elements");
  1248. }
  1249. }
  1250. } // End of class PathBetweenNodesEnumeration
  1251. } // End of class DefaultMutableTreeNode