home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / VCAFE.3.0A / Main.bin / DefaultMutableTreeNode.java < prev    next >
Text File  |  1998-11-09  |  46KB  |  1,493 lines

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