/** * 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()); }
/** * 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); }