/* DefaultMutableTreeNode.java --
   Copyright (C) 2002, 2004, 2005, 2006,  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing.tree;

import gnu.java.util.EmptyEnumeration;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Stack;
import java.util.Vector;


/**
 * A default implementation of the {@link MutableTreeNode} interface.
 *
 * @author Andrew Selkirk
 * @author Robert Schuster (robertschuster@fsfe.org)
 */
public class DefaultMutableTreeNode
  implements Cloneable, MutableTreeNode, Serializable
{
  private static final long serialVersionUID = -4298474751201349152L;

  /**
   * An empty enumeration, returned by {@link #children()} if a node has no
   * children.
   */
  public static final Enumeration<TreeNode> EMPTY_ENUMERATION =
    new EmptyEnumeration<TreeNode>();

  /**
   * The parent of this node (possibly <code>null</code>).
   */
  protected MutableTreeNode parent;

  /**
   * The child nodes for this node (may be empty).
   */
  protected Vector<MutableTreeNode> children = new Vector<MutableTreeNode>();

  /**
   * userObject
   */
  protected transient Object userObject;

  /**
   * allowsChildren
   */
  protected boolean allowsChildren;

  /**
   * Creates a <code>DefaultMutableTreeNode</code> object.
   * This is equivalent to <code>DefaultMutableTreeNode(null, true)</code>.
   */
  public DefaultMutableTreeNode()
  {
    this(null, true);
  }

  /**
   * Creates a <code>DefaultMutableTreeNode</code> object with the given
   * user object attached to it. This is equivalent to
   * <code>DefaultMutableTreeNode(userObject, true)</code>.
   *
   * @param userObject the user object (<code>null</code> permitted).
   */
  public DefaultMutableTreeNode(Object userObject)
  {
    this(userObject, true);
  }

  /**
   * Creates a <code>DefaultMutableTreeNode</code> object with the given
   * user object attached to it.
   *
   * @param userObject the user object (<code>null</code> permitted).
   * @param allowsChildren <code>true</code> if the code allows to add child
   * nodes, <code>false</code> otherwise
   */
  public DefaultMutableTreeNode(Object userObject, boolean allowsChildren)
  {
    this.userObject = userObject;
    this.allowsChildren = allowsChildren;
  }

  /**
   * Returns a clone of the node.  The clone contains a shallow copy of the
   * user object, and does not copy the parent node or the child nodes.
   *
   * @return A clone of the node.
   */
  public Object clone()
  {
    return new DefaultMutableTreeNode(this.userObject, this.allowsChildren);
  }

  /**
   * Returns a string representation of the node.  This implementation returns
   * <code>getUserObject().toString()</code>, or <code>null</code> if there
   * is no user object.
   *
   * @return A string representation of the node (possibly <code>null</code>).
   */
  public String toString()
  {
    if (userObject == null)
      return null;

    return userObject.toString();
  }

  /**
   * Adds a new child node to this node and sets this node as the parent of
   * the child node.  The child node must not be an ancestor of this node.
   * If the tree uses the {@link DefaultTreeModel}, you must subsequently
   * call {@link DefaultTreeModel#reload(TreeNode)}.
   *
   * @param child the child node (<code>null</code> not permitted).
   *
   * @throws IllegalStateException if {@link #getAllowsChildren()} returns
   *     <code>false</code>.
   * @throws IllegalArgumentException if {@link #isNodeAncestor} returns
   *     <code>true</code>.
   * @throws IllegalArgumentException if <code>child</code> is
   *     <code>null</code>.
   */
  public void add(MutableTreeNode child)
  {
    if (! allowsChildren)
      throw new IllegalStateException();

    if (child == null)
      throw new IllegalArgumentException();

    if (isNodeAncestor(child))
      throw new IllegalArgumentException("Cannot add ancestor node.");

    children.add(child);
    child.setParent(this);
  }

  /**
   * Returns the parent node of this node.
   *
   * @return The parent node (possibly <code>null</code>).
   */
  public TreeNode getParent()
  {
    return parent;
  }

  /**
   * Removes the child with the given index from this node.
   *
   * @param index the index (in the range <code>0</code> to
   *     <code>getChildCount() - 1</code>).
   *
   * @throws ArrayIndexOutOfBoundsException if <code>index</code> is outside
   *         the valid range.
   */
  public void remove(int index)
  {
    MutableTreeNode child = children.remove(index);
    child.setParent(null);
  }

  /**
   * Removes the given child from this node and sets its parent to
   * <code>null</code>.
   *
   * @param node the child node (<code>null</code> not permitted).
   *
   * @throws IllegalArgumentException if <code>node</code> is not a child of
   *     this node.
   * @throws IllegalArgumentException if <code>node</code> is null.
   */
  public void remove(MutableTreeNode node)
  {
    if (node == null)
      throw new IllegalArgumentException("Null 'node' argument.");
    if (node.getParent() != this)
      throw new IllegalArgumentException(
          "The given 'node' is not a child of this node.");
    children.remove(node);
    node.setParent(null);
  }

  /**
   * writeObject
   *
   * @param stream the output stream
   *
   * @exception IOException If an error occurs
   */
  private void writeObject(ObjectOutputStream stream)
    throws IOException
  {
    // TODO: Implement me.
  }

  /**
   * readObject
   *
   * @param stream the input stream
   *
   * @exception IOException If an error occurs
   * @exception ClassNotFoundException TODO
   */
  private void readObject(ObjectInputStream stream)
    throws IOException, ClassNotFoundException
  {
    // TODO: Implement me.
  }

  /**
   * Inserts given child node at the given index.
   *
   * @param node the child node (<code>null</code> not permitted).
   * @param index the index.
   *
   * @throws IllegalArgumentException if <code>node</code> is
   *     </code>null</code>.
   */
  public void insert(MutableTreeNode node, int index)
  {
    if (! allowsChildren)
      throw new IllegalStateException();

    if (node == null)
      throw new IllegalArgumentException("Null 'node' argument.");

    if (isNodeAncestor(node))
      throw new IllegalArgumentException("Cannot insert ancestor node.");

    children.insertElementAt(node, index);
  }

  /**
   * Returns a path to this node from the root.
   *
   * @return an array of tree nodes
   */
  public TreeNode[] getPath()
  {
    return getPathToRoot(this, 0);
  }

  /**
   * Returns an enumeration containing all children of this node.
   * <code>EMPTY_ENUMERATION</code> is returned if this node has no children.
   *
   * @return an enumeration of tree nodes
   */
  @SuppressWarnings("unchecked") // Required for API compatibility
  public Enumeration children()
  {
    if (children.size() == 0)
      return EMPTY_ENUMERATION;

    return children.elements();
  }

  /**
   * Set the parent node for this node.
   *
   * @param node the parent node
   */
  public void setParent(MutableTreeNode node)
  {
    parent = node;
  }

  /**
   * Returns the child node at a given index.
   *
   * @param index the index
   *
   * @return the child node
   */
  public TreeNode getChildAt(int index)
  {
    return children.elementAt(index);
  }

  /**
   * Returns the number of children of this node.
   *
   * @return the number of children
   */
  public int getChildCount()
  {
    return children.size();
  }

  /**
   * Returns the index of the specified child node, or -1 if the node is not
   * in fact a child of this node.
   *
   * @param node  the node (<code>null</code> not permitted).
   *
   * @return The index of the specified child node, or -1.
   *
   * @throws IllegalArgumentException if <code>node</code> is <code>null</code>.
   */
  public int getIndex(TreeNode node)
  {
    if (node == null)
      throw new IllegalArgumentException("Null 'node' argument.");
    return children.indexOf(node);
  }

  /**
   * Sets the flag that controls whether or not this node allows the addition /
   * insertion of child nodes.  If the flag is set to <code>false</code>, any
   * existing children are removed.
   *
   * @param allowsChildren  the flag.
   */
  public void setAllowsChildren(boolean allowsChildren)
  {
    if (!allowsChildren)
      removeAllChildren();
    this.allowsChildren = allowsChildren;
  }

  /**
   * getAllowsChildren
   *
   * @return boolean
   */
  public boolean getAllowsChildren()
  {
    return allowsChildren;
  }

  /**
   * Sets the user object for this node
   *
   * @param userObject the user object
   */
  public void setUserObject(Object userObject)
  {
    this.userObject = userObject;
  }

  /**
   * Returns the user object attached to this node. <code>null</code> is
   * returned when no user object is set.
   *
   * @return the user object
   */
  public Object getUserObject()
  {
    return userObject;
  }

  /**
   * Removes this node from its parent.
   */
  public void removeFromParent()
  {
    parent.remove(this);
    parent = null;
  }

  /**
   * Removes all child nodes from this node.
   */
  public void removeAllChildren()
  {
    for (int i = getChildCount() - 1; i >= 0; i--)
      remove(i);
  }

  /**
   * Returns <code>true</code> if <code>node</code> is an ancestor of this
   * tree node, and <code>false</code> otherwise.  An ancestor node is any of:
   * <ul>
   * <li>this tree node;</li>
   * <li>the parent node (if there is one);</li>
   * <li>any ancestor of the parent node;</li>
   * </ul>
   * If <code>node</code> is <code>null</code>, this method returns
   * <code>false</code>.
   *
   * @param node  the node (<code>null</code> permitted).
   *
   * @return A boolean.
   */
  public boolean isNodeAncestor(TreeNode node)
  {
    if (node == null)
      return false;

    TreeNode current = this;

    while (current != null && current != node)
      current = current.getParent();

    return current == node;
  }

  /**
   * Returns <code>true</code> if <code>node</code> is a descendant of this
   * tree node, and <code>false</code> otherwise.  A descendant node is any of:
   * <ul>
   * <li>this tree node;</li>
   * <li>the child nodes belonging to this tree node, if there are any;</li>
   * <li>any descendants of the child nodes;</li>
   * </ul>
   * If <code>node</code> is <code>null</code>, this method returns
   * <code>false</code>.
   *
   * @param node  the node (<code>null</code> permitted).
   *
   * @return A boolean.
   */
  public boolean isNodeDescendant(DefaultMutableTreeNode node)
  {
    if (node == null)
      return false;

    TreeNode current = node;

    while (current != null
           && current != this)
      current = current.getParent();

    return current == this;
  }

  /**
   * getSharedAncestor
   *
   * @param node TODO
   *
   * @return TreeNode
   */
  public TreeNode getSharedAncestor(DefaultMutableTreeNode node)
  {
    TreeNode current = this;
    ArrayList<TreeNode> list = new ArrayList<TreeNode>();

    while (current != null)
      {
        list.add(current);
        current = current.getParent();
      }

    current = node;

    while (current != null)
      {
        if (list.contains(current))
          return current;

        current = current.getParent();
      }

    return null;
  }

  /**
   * isNodeRelated
   *
   * @param node TODO
   *
   * @return boolean
   */
  public boolean isNodeRelated(DefaultMutableTreeNode node)
  {
    if (node == null)
      return false;

    return node.getRoot() == getRoot();
  }

  /**
   * getDepth
   *
   * @return int
   */
  public int getDepth()
  {
    if ((! allowsChildren)
        || children.size() == 0)
      return 0;

    Stack<Integer> stack = new Stack<Integer>();
    stack.push(new Integer(0));
    TreeNode node = getChildAt(0);
    int depth = 0;
    int current = 1;

    while (! stack.empty())
      {
        if (node.getChildCount() != 0)
          {
            node = node.getChildAt(0);
            stack.push(new Integer(0));
            current++;
          }
        else
          {
            if (current > depth)
              depth = current;

            int size;
            int index;

            do
              {
                node = node.getParent();
                size = node.getChildCount();
                index = stack.pop().intValue() + 1;
                current--;
              }
            while (index >= size
                   && node != this);

            if (index < size)
              {
                node = node.getChildAt(index);
                stack.push(new Integer(index));
                current++;
              }
          }
      }

    return depth;
  }

  /**
   * getLevel
   *
   * @return int
   */
  public int getLevel()
  {
    int count = -1;
    TreeNode current = this;

    do
      {
        current = current.getParent();
        count++;
      }
    while (current != null);

    return count;
  }

  /**
   * getPathToRoot
   *
   * @param node TODO
   * @param depth TODO
   *
   * @return TreeNode[]
   */
  protected TreeNode[] getPathToRoot(TreeNode node, int depth)
  {
    if (node == null)
      {
        if (depth == 0)
          return null;

        return new TreeNode[depth];
      }

    TreeNode[] path = getPathToRoot(node.getParent(), depth + 1);
    path[path.length - depth - 1] = node;
    return path;
  }

  /**
   * getUserObjectPath
   *
   * @return Object[]
   */
  public Object[] getUserObjectPath()
  {
    TreeNode[] path = getPathToRoot(this, 0);
    Object[] object = new Object[path.length];

    for (int index = 0; index < path.length; ++index)
      object[index] = ((DefaultMutableTreeNode) path[index]).getUserObject();

    return object;
  }

  /**
   * Returns the root node by iterating the parents of this node.
   *
   * @return the root node
   */
  public TreeNode getRoot()
  {
    TreeNode current = this;
    TreeNode check = current.getParent();

    while (check != null)
      {
        current = check;
        check = current.getParent();
      }

    return current;
  }

  /**
   * Tells whether this node is the root node or not.
   *
   * @return <code>true</code> if this is the root node,
   * <code>false</code>otherwise
   */
  public boolean isRoot()
  {
    return parent == null;
  }

  /**
   * getNextNode
   *
   * @return DefaultMutableTreeNode
   */
  public DefaultMutableTreeNode getNextNode()
  {
    // Return first child.
    if (getChildCount() != 0)
      return (DefaultMutableTreeNode) getChildAt(0);

    // Return next sibling (if needed the sibling of some parent).
    DefaultMutableTreeNode node = this;
    DefaultMutableTreeNode sibling;

    do
      {
        sibling = node.getNextSibling();
        node = (DefaultMutableTreeNode) node.getParent();
      }
    while (sibling == null &&
           node != null);

    // Return sibling.
    return sibling;
  }

  /**
   * getPreviousNode
   *
   * @return DefaultMutableTreeNode
   */
  public DefaultMutableTreeNode getPreviousNode()
  {
    // Return null if no parent.
    if (parent == null)
      return null;

    DefaultMutableTreeNode sibling = getPreviousSibling();

    // Return parent if no sibling.
    if (sibling == null)
      return (DefaultMutableTreeNode) parent;

    // Return last leaf of sibling.
    if (sibling.getChildCount() != 0)
      return sibling.getLastLeaf();

    // Return sibling.
    return sibling;
  }

  /**
   * preorderEnumeration
   *
   * @return Enumeration
   */
  @SuppressWarnings("unchecked") // Required for API compatibility
  public Enumeration preorderEnumeration()
  {
    return new PreorderEnumeration(this);
  }

  /**
   * postorderEnumeration
   *
   * @return Enumeration
   */
  @SuppressWarnings("unchecked") // Required for API compatibility
  public Enumeration postorderEnumeration()
  {
    return new PostorderEnumeration(this);
  }

  /**
   * breadthFirstEnumeration
   *
   * @return Enumeration
   */
  @SuppressWarnings("unchecked") // Required for API compatibility
  public Enumeration breadthFirstEnumeration()
  {
    return new BreadthFirstEnumeration(this);
  }

  /**
   * depthFirstEnumeration
   *
   * @return Enumeration
   */
  @SuppressWarnings("unchecked") // Required for API compatibility
  public Enumeration depthFirstEnumeration()
  {
    return postorderEnumeration();
  }

  /**
   * pathFromAncestorEnumeration
   *
   * @param node TODO
   *
   * @return Enumeration
   */
  @SuppressWarnings("unchecked") // Required for API compatibility
  public Enumeration pathFromAncestorEnumeration(TreeNode node)
  {
    if (node == null)
      throw new IllegalArgumentException();

    TreeNode parent = this;
    Vector<TreeNode> nodes = new Vector<TreeNode>();
    nodes.add(this);

    while (parent != node && parent != null)
      {
        parent = parent.getParent();
        nodes.add(0, parent);
      }

    if (parent != node)
      throw new IllegalArgumentException();

    return nodes.elements();
  }

  /**
   * Returns <code>true</code> if <code>node</code> is a child of this tree
   * node, and <code>false</code> otherwise.  If <code>node</code> is
   * <code>null</code>, this method returns <code>false</code>.
   *
   * @param node  the node (<code>null</code> permitted).
   *
   * @return A boolean.
   */
  public boolean isNodeChild(TreeNode node)
  {
    if (node == null)
      return false;

    return node.getParent() == this;
  }

  /**
   * Returns the first child node belonging to this tree node.
   *
   * @return The first child node.
   *
   * @throws NoSuchElementException if this tree node has no children.
   */
  public TreeNode getFirstChild()
  {
    return children.firstElement();
  }

  /**
   * Returns the last child node belonging to this tree node.
   *
   * @return The last child node.
   *
   * @throws NoSuchElementException if this tree node has no children.
   */
  public TreeNode getLastChild()
  {
    return children.lastElement();
  }

  /**
   * Returns the next child after the specified <code>node</code>, or
   * <code>null</code> if there is no child after the specified
   * <code>node</code>.
   *
   * @param node  a child of this node (<code>null</code> not permitted).
   *
   * @return The next child, or <code>null</code>.
   *
   * @throws IllegalArgumentException if <code>node</code> is not a child of
   *     this node, or is <code>null</code>.
   */
  public TreeNode getChildAfter(TreeNode node)
  {
    if (node == null || node.getParent() != this)
      throw new IllegalArgumentException();

    int index = getIndex(node) + 1;

    if (index == getChildCount())
      return null;

    return getChildAt(index);
  }

  /**
   * Returns the previous child before the specified <code>node</code>, or
   * <code>null</code> if there is no child before the specified
   * <code>node</code>.
   *
   * @param node  a child of this node (<code>null</code> not permitted).
   *
   * @return The previous child, or <code>null</code>.
   *
   * @throws IllegalArgumentException if <code>node</code> is not a child of
   *     this node, or is <code>null</code>.
   */
  public TreeNode getChildBefore(TreeNode node)
  {
    if (node == null || node.getParent() != this)
      throw new IllegalArgumentException();

    int index = getIndex(node) - 1;

    if (index < 0)
      return null;

    return getChildAt(index);
  }

  /**
   * Returns <code>true</code> if this tree node and <code>node</code> share
   * the same parent.  If <code>node</code> is this tree node, the method
   * returns <code>true</code> and if <code>node</code> is <code>null</code>
   * this method returns <code>false</code>.
   *
   * @param node  the node (<code>null</code> permitted).
   *
   * @return A boolean.
   */
  public boolean isNodeSibling(TreeNode node)
  {
    if (node == null)
      return false;
    if (node == this)
      return true;
    return node.getParent() == getParent() && getParent() != null;
  }

  /**
   * Returns the number of siblings for this tree node.  If the tree node has
   * a parent, this method returns the child count for the parent, otherwise
   * it returns <code>1</code>.
   *
   * @return The sibling count.
   */
  public int getSiblingCount()
  {
    if (parent == null)
      return 1;

    return parent.getChildCount();
  }

  /**
   * Returns the next sibling for this tree node.  If this node has no parent,
   * or this node is the last child of its parent, this method returns
   * <code>null</code>.
   *
   * @return The next sibling, or <code>null</code>.
   */
  public DefaultMutableTreeNode getNextSibling()
  {
    if (parent == null)
      return null;

    int index = parent.getIndex(this) + 1;

    if (index == parent.getChildCount())
      return null;

    return (DefaultMutableTreeNode) parent.getChildAt(index);
  }

  /**
   * Returns the previous sibling for this tree node.  If this node has no
   * parent, or this node is the first child of its parent, this method returns
   * <code>null</code>.
   *
   * @return The previous sibling, or <code>null</code>.
   */
  public DefaultMutableTreeNode getPreviousSibling()
  {
    if (parent == null)
      return null;

    int index = parent.getIndex(this) - 1;

    if (index < 0)
      return null;

    return (DefaultMutableTreeNode) parent.getChildAt(index);
  }

  /**
   * Returns <code>true</code> if this tree node is a lead node (that is, it
   * has no children), and <code>false</otherwise>.
   *
   * @return A boolean.
   */
  public boolean isLeaf()
  {
    return children.size() == 0;
  }

  /**
   * Returns the first leaf node that is a descendant of this node.  Recall
   * that a node is its own descendant, so if this node has no children then
   * it is returned as the first leaf.
   *
   * @return The first leaf node.
   */
  public DefaultMutableTreeNode getFirstLeaf()
  {
    TreeNode current = this;

    while (current.getChildCount() > 0)
      current = current.getChildAt(0);

    return (DefaultMutableTreeNode) current;
  }

  /**
   * Returns the last leaf node that is a descendant of this node.  Recall
   * that a node is its own descendant, so if this node has no children then
   * it is returned as the last leaf.
   *
   * @return The first leaf node.
   */
  public DefaultMutableTreeNode getLastLeaf()
  {
    TreeNode current = this;
    int size = current.getChildCount();

    while (size > 0)
      {
        current = current.getChildAt(size - 1);
        size = current.getChildCount();
      }

    return (DefaultMutableTreeNode) current;
  }

  /**
   * Returns the next leaf node after this tree node.
   *
   * @return The next leaf node, or <code>null</code>.
   */
  public DefaultMutableTreeNode getNextLeaf()
  {
    // if there is a next sibling, return its first leaf
    DefaultMutableTreeNode sibling = getNextSibling();
    if (sibling != null)
      return sibling.getFirstLeaf();
    // otherwise move up one level and try again...
    if (parent != null)
      return ((DefaultMutableTreeNode) parent).getNextLeaf();
    return null;
  }

  /**
   * Returns the previous leaf node before this tree node.
   *
   * @return The previous leaf node, or <code>null</code>.
   */
  public DefaultMutableTreeNode getPreviousLeaf()
  {
    // if there is a previous sibling, return its last leaf
    DefaultMutableTreeNode sibling = getPreviousSibling();
    if (sibling != null)
      return sibling.getLastLeaf();
    // otherwise move up one level and try again...
    if (parent != null)
      return ((DefaultMutableTreeNode) parent).getPreviousLeaf();
    return null;
  }

  /**
   * getLeafCount
   *
   * @return int
   */
  public int getLeafCount()
  {
    int count = 0;
    Enumeration<?> e = depthFirstEnumeration();

    while (e.hasMoreElements())
      {
        TreeNode current = (TreeNode) e.nextElement();

        if (current.isLeaf())
          count++;
      }

    return count;
  }

  /** Provides an enumeration of a tree in breadth-first traversal
   * order.
   */
  static class BreadthFirstEnumeration implements Enumeration<TreeNode>
  {

      LinkedList<TreeNode> queue = new LinkedList<TreeNode>();

      BreadthFirstEnumeration(TreeNode node)
      {
          queue.add(node);
      }

      public boolean hasMoreElements()
      {
          return !queue.isEmpty();
      }

      @SuppressWarnings("unchecked")
      public TreeNode nextElement()
      {
          if (queue.isEmpty())
              throw new NoSuchElementException("No more elements left.");

          TreeNode node = queue.removeFirst();

          Enumeration<TreeNode> children =
            (Enumeration<TreeNode>) node.children();
          while (children.hasMoreElements())
              queue.add(children.nextElement());

          return node;
      }
  }

  /** Provides an enumeration of a tree traversing it
   * preordered.
   */
  static class PreorderEnumeration implements Enumeration<TreeNode>
  {
          TreeNode next;

      Stack<Enumeration<TreeNode>> childrenEnums =
        new Stack<Enumeration<TreeNode>>();

      @SuppressWarnings("unchecked")
      PreorderEnumeration(TreeNode node)
      {
          next = node;
          childrenEnums.push((Enumeration<TreeNode>) node.children());
      }

      public boolean hasMoreElements()
      {
          return next != null;
      }

      public TreeNode nextElement()
      {
          if (next == null)
              throw new NoSuchElementException("No more elements left.");

          TreeNode current = next;

          Enumeration<TreeNode> children = childrenEnums.peek();

          // Retrieves the next element.
          next = traverse(children);

          return current;
      }

      @SuppressWarnings("unchecked")
      private TreeNode traverse(Enumeration<TreeNode> children)
      {
          // If more children are available step down.
          if (children.hasMoreElements())
          {
              TreeNode child = children.nextElement();
              childrenEnums.push((Enumeration<TreeNode>) child.children());

              return child;
          }

          // If no children are left, we return to a higher level.
          childrenEnums.pop();

          // If there are no more levels left, there is no next
          // element to return.
          if (childrenEnums.isEmpty())
              return null;
          else
          {
              return traverse(childrenEnums.peek());
          }
      }
   }

  /** Provides an enumeration of a tree traversing it
   * postordered (= depth-first).
   */
   static class PostorderEnumeration implements Enumeration<TreeNode>
   {

       Stack<TreeNode> nodes = new Stack<TreeNode>();
       Stack<Enumeration<TreeNode>> childrenEnums =
         new Stack<Enumeration<TreeNode>>();

       @SuppressWarnings("unchecked")
       PostorderEnumeration(TreeNode node)
       {
           nodes.push(node);
           childrenEnums.push((Enumeration<TreeNode>) node.children());
       }

       public boolean hasMoreElements()
       {
           return !nodes.isEmpty();
       }

       public TreeNode nextElement()
       {
           if (nodes.isEmpty())
               throw new NoSuchElementException("No more elements left!");

           Enumeration<TreeNode> children = childrenEnums.peek();

           return traverse(children);
       }

       @SuppressWarnings("unchecked")
       private TreeNode traverse(Enumeration<TreeNode> children)
       {
           if (children.hasMoreElements())
           {
               TreeNode node = children.nextElement();
               nodes.push(node);

               Enumeration<TreeNode> newChildren =
                 (Enumeration<TreeNode>) node.children();
               childrenEnums.push(newChildren);

               return traverse(newChildren);
           }
           else
           {
               childrenEnums.pop();

               // Returns the node whose children
               // have all been visited. (= postorder)
               TreeNode next = nodes.peek();
               nodes.pop();

               return next;
           }
       }

    }

}
