/**
   * Returns the node that follows this node in a preorder traversal of this node's tree. Returns
   * null if this node is the last node of the traversal. This is an inefficient way to traverse the
   * entire tree; use an enumeration, instead.
   *
   * @see #preorderEnumeration
   * @return the node that follows this node in a preorder traversal, or null if this node is last
   */
  public DefaultMutableTreeNode getNextNode() {
    if (getChildCount() == 0) {
      // No children, so look for nextSibling
      DefaultMutableTreeNode nextSibling = getNextSibling();

      if (nextSibling == null) {
        DefaultMutableTreeNode aNode = (DefaultMutableTreeNode) getParent();

        do {
          if (aNode == null) {
            return null;
          }

          nextSibling = aNode.getNextSibling();
          if (nextSibling != null) {
            return nextSibling;
          }

          aNode = (DefaultMutableTreeNode) aNode.getParent();
        } while (true);
      } else {
        return nextSibling;
      }
    } else {
      return (DefaultMutableTreeNode) getChildAt(0);
    }
  }
  /**
   * Finds and returns the last leaf that is a descendant of this node -- either this node or its
   * last child's last leaf. Returns this node if it is a leaf.
   *
   * @see #isLeaf
   * @see #isNodeDescendant
   * @return the last leaf in the subtree rooted at this node
   */
  public DefaultMutableTreeNode getLastLeaf() {
    DefaultMutableTreeNode node = this;

    while (!node.isLeaf()) {
      node = (DefaultMutableTreeNode) node.getLastChild();
    }

    return node;
  }
  /**
   * Returns the leaf before this node or null if this node is the first leaf in the tree.
   *
   * <p>In this implementation of the <code>MutableNode</code> interface, this operation is very
   * inefficient. In order to determine the previous node, this method first performs a linear
   * search in the parent's child-list in order to find the current node.
   *
   * <p>That implementation makes the operation suitable for short traversals from a known position.
   * But to traverse all of the leaves in the tree, you should use <code>depthFirstEnumeration
   * </code> to enumerate the nodes in the tree and use <code>isLeaf</code> on each node to
   * determine which are leaves.
   *
   * @see #depthFirstEnumeration
   * @see #isLeaf
   * @return returns the leaf before this node
   */
  public DefaultMutableTreeNode getPreviousLeaf() {
    DefaultMutableTreeNode previousSibling;
    DefaultMutableTreeNode myParent = (DefaultMutableTreeNode) getParent();

    if (myParent == null) return null;

    previousSibling = getPreviousSibling(); // linear search

    if (previousSibling != null) return previousSibling.getLastLeaf();

    return myParent.getPreviousLeaf(); // tail recursion
  }
  /**
   * Returns the leaf after this node or null if this node is the last leaf in the tree.
   *
   * <p>In this implementation of the <code>MutableNode</code> interface, this operation is very
   * inefficient. In order to determine the next node, this method first performs a linear search in
   * the parent's child-list in order to find the current node.
   *
   * <p>That implementation makes the operation suitable for short traversals from a known position.
   * But to traverse all of the leaves in the tree, you should use <code>depthFirstEnumeration
   * </code> to enumerate the nodes in the tree and use <code>isLeaf</code> on each node to
   * determine which are leaves.
   *
   * @see #depthFirstEnumeration
   * @see #isLeaf
   * @return returns the next leaf past this node
   */
  public DefaultMutableTreeNode getNextLeaf() {
    DefaultMutableTreeNode nextSibling;
    DefaultMutableTreeNode myParent = (DefaultMutableTreeNode) getParent();

    if (myParent == null) return null;

    nextSibling = getNextSibling(); // linear search

    if (nextSibling != null) return nextSibling.getFirstLeaf();

    return myParent.getNextLeaf(); // tail recursion
  }
  /**
   * Returns the previous sibling of this node in the parent's children array. Returns null if this
   * node has no parent or is the parent's first child. This method performs a linear search that is
   * O(n) where n is the number of children.
   *
   * @return the sibling of this node that immediately precedes this node
   */
  public DefaultMutableTreeNode getPreviousSibling() {
    DefaultMutableTreeNode retval;

    DefaultMutableTreeNode myParent = (DefaultMutableTreeNode) getParent();

    if (myParent == null) {
      retval = null;
    } else {
      retval = (DefaultMutableTreeNode) myParent.getChildBefore(this); // linear search
    }

    if (retval != null && !isNodeSibling(retval)) {
      throw new Error("child of parent is not a sibling");
    }

    return retval;
  }
  /**
   * Returns the node that precedes this node in a preorder traversal of this node's tree. Returns
   * <code>null</code> if this node is the first node of the traversal -- the root of the tree. This
   * is an inefficient way to traverse the entire tree; use an enumeration, instead.
   *
   * @see #preorderEnumeration
   * @return the node that precedes this node in a preorder traversal, or null if this node is the
   *     first
   */
  public DefaultMutableTreeNode getPreviousNode() {
    DefaultMutableTreeNode previousSibling;
    DefaultMutableTreeNode myParent = (DefaultMutableTreeNode) getParent();

    if (myParent == null) {
      return null;
    }

    previousSibling = getPreviousSibling();

    if (previousSibling != null) {
      if (previousSibling.getChildCount() == 0) return previousSibling;
      else return previousSibling.getLastLeaf();
    } else {
      return myParent;
    }
  }
  /**
   * Overridden to make clone public. Returns a shallow copy of this node; the new node has no
   * parent or children and has a reference to the same user object, if any.
   *
   * @return a copy of this node
   */
  public Object clone() {
    DefaultMutableTreeNode newNode;

    try {
      newNode = (DefaultMutableTreeNode) super.clone();

      // shallow copy -- the new node has no parent or children
      newNode.children = null;
      newNode.parent = null;

    } catch (CloneNotSupportedException e) {
      // Won't happen because we implement Cloneable
      throw new Error(e.toString());
    }

    return newNode;
  }
  /**
   * Returns the nearest common ancestor to this node and <code>aNode</code>. Returns null, if no
   * such ancestor exists -- if this node and <code>aNode</code> are in different trees or if <code>
   * aNode</code> is null. A node is considered an ancestor of itself.
   *
   * @see #isNodeAncestor
   * @see #isNodeDescendant
   * @param aNode node to find common ancestor with
   * @return nearest ancestor common to this node and <code>aNode</code>, or null if none
   */
  public TreeNode getSharedAncestor(DefaultMutableTreeNode aNode) {
    if (aNode == this) {
      return this;
    } else if (aNode == null) {
      return null;
    }

    int level1, level2, diff;
    TreeNode node1, node2;

    level1 = getLevel();
    level2 = aNode.getLevel();

    if (level2 > level1) {
      diff = level2 - level1;
      node1 = aNode;
      node2 = this;
    } else {
      diff = level1 - level2;
      node1 = this;
      node2 = aNode;
    }

    // Go up the tree until the nodes are at the same level
    while (diff > 0) {
      node1 = node1.getParent();
      diff--;
    }

    // Move up the tree until we find a common ancestor.  Since we know
    // that both nodes are at the same level, we won't cross paths
    // unknowingly (if there is a common ancestor, both nodes hit it in
    // the same iteration).

    do {
      if (node1 == node2) {
        return node1;
      }
      node1 = node1.getParent();
      node2 = node2.getParent();
    } while (node1 != null); // only need to check one -- they're at the
    // same level so if one is null, the other is

    if (node1 != null || node2 != null) {
      throw new Error("nodes should be null");
    }

    return null;
  }
 /**
  * Returns true if and only if <code>aNode</code> is in the same tree as this node. Returns false
  * if <code>aNode</code> is null.
  *
  * @see #getSharedAncestor
  * @see #getRoot
  * @return true if <code>aNode</code> is in the same tree as this node; false if <code>aNode
  *     </code> is null
  */
 public boolean isNodeRelated(DefaultMutableTreeNode aNode) {
   return (aNode != null) && (getRoot() == aNode.getRoot());
 }
示例#10
0
  /**
   * Returns true if <code>anotherNode</code> is a descendant of this node -- if it is this node,
   * one of this node's children, or a descendant of one of this node's children. Note that a node
   * is considered a descendant of itself. If <code>anotherNode</code> is null, returns false. This
   * operation is at worst O(h) where h is the distance from the root to <code>anotherNode</code>.
   *
   * @see #isNodeAncestor
   * @see #getSharedAncestor
   * @param anotherNode node to test as descendant of this node
   * @return true if this node is an ancestor of <code>anotherNode</code>
   */
  public boolean isNodeDescendant(DefaultMutableTreeNode anotherNode) {
    if (anotherNode == null) return false;

    return anotherNode.isNodeAncestor(this);
  }