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