home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / jfc.bin / DefaultMutableTreeNode.java < prev    next >
Text File  |  1998-02-26  |  42KB  |  1,445 lines

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