@Override public E getParentElement(N node) { return inner.getParentElement(node); }
@Override public E getParentElement(N node) { E element = inner.getParentElement(node); while (element != null) { switch (getSkipLevel(element)) { case NONE: return element; case SHALLOW: element = inner.getParentElement(element); break; case DEEP: // Shouldn't really happen, but better handle it element = inner.getParentElement(element); break; case INVALID: return null; default: throw new RuntimeException("Unimplemented"); } } return null; }
/** * Same as {@link #enclosingElement(ReadableDocument, Point)}, except * does it for a node. So if it is an element, return it, if it is * a text node, return its parent. */ public static <N, E extends N, T extends N> E enclosingElement( ReadableDocument<N,E,T> doc, N node) { E el = doc.asElement(node); return el == null ? doc.getParentElement(node) : el; }
/** * Construct a point before the given node */ public static <N, E extends N, T extends N> El<N> before( ReadableDocument<N,E,T> doc, N node) { return new El<N>(doc.getParentElement(node), node); }
/** * Useful argument checking method for validating that a nodeAfter is * null or the child of the given parent * * @param doc * @param parent * @param nodeAfter * @param msgPrefix string to prepend to exception, if thrown */ public static <N, E extends N> void checkRelationship( ReadableDocument<N, E, ?> doc, E parent, N nodeAfter, String msgPrefix) { Preconditions.checkNotNull(parent, "Container must not be null"); if (nodeAfter != null && doc.getParentElement(nodeAfter) != parent) { throw new IllegalArgumentException( msgPrefix + ": nodeAfter must be null or a child of parent"); } }
/** * Checks whether a given node is an ancestory of another (either inclusive or exclusive). * @param doc Document for tree traversal * @param ancestor A (non-null) node to check to check if the next param is a descendant of * @param child The node whose ancestory is being checked * @param canEqual The result if the two nodes are equal */ public static <N, E extends N, T extends N> boolean isAncestor(ReadableDocument<N, E, T> doc, N ancestor, N child, boolean canEqual) { Preconditions.checkNotNull(ancestor, "Shouldn't check ancestry of a null node"); // keep going up the tree until we break out the parent (complexity = depth of child) while (child != null) { if (ancestor == child) { return canEqual; } canEqual = true; // now equality represents absolute descendancy child = doc.getParentElement(child); } return false; // no match } }
/** * Construct a point after the given node */ public static <N, E extends N, T extends N> El<N> after( ReadableDocument<N,E,T> doc, N node) { return new El<N>(doc.getParentElement(node), doc.getNextSibling(node)); }
node1 = doc.getParentElement(node1); node2 = doc.getParentElement(node2);
/** * Ensures the given point is at a node boundary, possibly splitting a text * node in order to do so, in which case a new point is returned. * * @param point * @return a point at the same place as the input point, guaranteed to be at * a node boundary. */ public static <N, T extends N> Point.El<N> ensureNodeBoundary(Point<N> point, ReadableDocument<N, ?, T> doc, TextNodeOrganiser<T> textNodeOrganiser) { Point.Tx<N> textPoint = point.asTextPoint(); if (textPoint != null) { T textNode = doc.asText(textPoint.getContainer()); N maybeSecond = textNodeOrganiser.splitText(textNode, textPoint.getTextOffset()); if (maybeSecond != null) { return Point.inElement(doc.getParentElement(maybeSecond), maybeSecond); } else { return Point.inElement(doc.getParentElement(textNode), doc.getNextSibling(textNode)); } } else { return point.asElementPoint(); } }
/** * Step out of end tags, so we get something that is either in a text node, * or the node after our point in a pre-order traversal */ private static <N, E extends N, T extends N> void getNodeAfterOutwards( ReadableDocument<N, E, T> doc, Point<N> point, NodeOffset<N> output) { N node; int startOffset; if (point.isInTextNode()) { node = point.getContainer(); startOffset = point.getTextOffset(); } else { node = point.getNodeAfter(); if (node == null) { N parent = point.getContainer(); while (parent != null) { node = doc.getNextSibling(parent); if (node != null) { break; } parent = doc.getParentElement(parent); } } startOffset = 0; } output.node = node; output.offset = startOffset; }
N nodeAfter; if (location.isInTextNode()) { el = doc.getParentElement(location.getContainer()); nodeAfter = doc.getNextSibling(location.getContainer()); if (predicate.apply(doc, el)) { el = doc.getParentElement(el);
/** * If the given point is equivalent to the end of the inside of an element, * return that element, otherwise null. */ @SuppressWarnings("unchecked") public static <N, E extends N, T extends N> E elementEndingAt( ReadableDocument<N,E,T> doc, Point<N> point) { if (point.isInTextNode()) { if (point.getTextOffset() < doc.getLength((T) point.getContainer())) { return null; } else if (doc.getNextSibling(point.getContainer()) == null) { return doc.getParentElement(point.getContainer()); } else { return null; } } else { return point.getNodeAfter() == null ? (E) point.getContainer() : null; } }
parent = fullDoc.getParentElement(at); } else if (lastBefore != null) { parent = fullDoc.getParentElement(lastBefore);
return next; start = doc.getParentElement(start);