/** * Returns {@code true} when a node is a root node. * <p> * It is non null and has a null parent. * * @param node The node. * @return {@code true} when {@code node} is a root. */ public final boolean isRoot(N node) { return node != null && getParent(node) == null; }
/** * Returns {@code true} when a first node is strictly over a second node. * * @param node1 The first node. * @param node2 The second node. * @return {@code true} when {@code node1} is strictly over {@code node2}. */ public final boolean isStrictlyOver(N node1, N node2) { N index2 = node2; while (index2 != null) { if (index2 == node1) { return index2 != node2; } index2 = getParent(index2); } // Here, index2 == null return false; }
/** * Returns {@code true} when a first node is over or equal to a second node. * * @param node1 The first node. * @param node2 The second node. * @return {@code true} when {@code node1} is over or equal to {@code node2}. */ public final boolean isOverOrEqual(N node1, N node2) { N index2 = node2; while (index2 != null) { if (index2 == node1) { return true; } index2 = getParent(index2); } // Here, index2 == null // Usually false. Just do this for the case where node1 == node2 == null return node1 == node2; }
/** * Returns the root of a node. * <p> * It is the highest ancestor that has no parent.<br> * It may be the node itself (when it is a root). * * @param node The node. <em>MUST NOT</em> be null. * @return The root of {@code node}. */ public final N getRoot(N node) { Checks.isNotNull(node, NODE); N index = node; while (getParent(index) != null) { index = getParent(index); } return index; }
/** * Returns the depth of a node. * <p> * It is the number of edges between the node and the root.<br> * Depth of root node is 0. * * @param node The node. * @return The depth of {@code node}. */ public final int getDepth(N node) { Checks.isNotNull(node, NODE); int depth = 0; N index = node; while (getParent(index) != null) { index = getParent(index); depth++; } return depth; }
/** * Returns the index of a child node in its parent's children. * * @param node The node. * @return The index of {@code node}, or {@code -1} if {@code node} is a root. */ public final int getIndex(N node) { Checks.isNotNull(node, NODE); if (getParent(node) == null) { return -1; } else { return Iterables.indexOf(getChildren(getParent(node)), node); } }
public N[] getPath(N node) { Checks.isNotNull(node, NODE); final int length = getDepth(node) + 1; @SuppressWarnings("unchecked") final N[] path = (N[]) new Object[length]; N iter = node; int index = length - 1; while (iter != null) { path[index] = iter; iter = getParent(iter); index--; } return path; } }
/** * Returns the qualified index of a node. * <p> * It is the array of indices of the node and its ancestors, excluding the root node.<br> * A root node has an empty qindex. * * @param node The node. * @return The qualified index of {@code node} */ public final int[] getQIndex(N node) { Checks.isNotNull(node, NODE); final int length = getDepth(node); final int[] result = new int[length]; N iter = node; int index = length - 1; while (index >= 0) { result[index] = getIndex(iter); iter = getParent(iter); index--; } return result; }