/** * Generic (model-independent) method to determine the relative position of two node in document * order. The nodes must be in the same tree. * * @param first The first node * @param second The second node, whose position is to be compared with the first node * @return -1 if this node precedes the other node, +1 if it follows the other node, or 0 if they * are the same node. (In this case, isSameNode() will always return true, and the two nodes * will produce the same result for generateId()) */ public static int compareOrder(SiblingCountingNode first, SiblingCountingNode second) { NodeInfo ow = second; // are they the same node? if (first.isSameNode(second)) { return 0; } // are they siblings (common case) if (first.getParent().isSameNode(second.getParent())) { return first.getSiblingPosition() - second.getSiblingPosition(); } // find the depths of both nodes in the tree int depth1 = 0; int depth2 = 0; NodeInfo p1 = first; NodeInfo p2 = second; while (p1 != null) { depth1++; p1 = p1.getParent(); } while (p2 != null) { depth2++; p2 = p2.getParent(); } // move up one branch of the tree so we have two nodes on the same level p1 = first; while (depth1 > depth2) { p1 = p1.getParent(); if (p1.isSameNode(second)) { return +1; } depth1--; } p2 = ow; while (depth2 > depth1) { p2 = p2.getParent(); if (p2.isSameNode(first)) { return -1; } depth2--; } // now move up both branches in sync until we find a common parent while (true) { NodeInfo par1 = p1.getParent(); NodeInfo par2 = p2.getParent(); if (par1 == null || par2 == null) { throw new NullPointerException("DOM tree compare - internal error"); } if (par1.isSameNode(par2)) { return ((SiblingCountingNode) p1).getSiblingPosition() - ((SiblingCountingNode) p2).getSiblingPosition(); } p1 = par1; p2 = par2; } }
/** * Get a character string that uniquely identifies this node and that collates nodes into document * order * * @return a string. The string is always interned so keys can be compared using "==". */ public static String getSequentialKey(SiblingCountingNode node) { // TODO: this was designed so it could be used for sorting nodes into document // order, but is not currently used that way. StringBuffer key = new StringBuffer(); while (!(node instanceof DocumentInfo)) { key.insert(0, alphaKey(node.getSiblingPosition())); node = (SiblingCountingNode) node.getParent(); } key.insert(0, "w" + node.getDocumentNumber()); return key.toString().intern(); }