@Override public T asText(N node) { return inner.asText(node); }
/** * @param doc * @param node * @return true if node prefers to be output inline */ private <E extends N, T extends N> boolean isInline( ReadableDocument<N, E, T> doc, N node) { E element = doc.asElement(node); T text = doc.asText(node); return text != null || "|b|u|i|".contains("|" + doc.getTagName(element).toLowerCase() + "|"); }
/** * This method returns the last point in a sequence of text node in the given direction. * * We guarantee that the return value is non-null and inside a text node. * * @return the last point in the text sequence as a text point. */ private static <N, E extends N, T extends N> Tx<N> lastPointInTextSequence( ReadableDocument<N, E, T> doc, Tx<N> start, boolean forward) { Tx<N> ret; if (forward) { T t = doc.asText(start.getCanonicalNode()); T next = doc.asText(doc.getNextSibling(t)); while (next != null) { t = next; next = doc.asText(doc.getNextSibling(t)); } ret = Point.<N> inText(t, doc.getLength(t)); } else { T t = doc.asText(start.getCanonicalNode()); T prev = doc.asText(doc.getPreviousSibling(t)); while (prev != null) { t = prev; prev = doc.asText(doc.getPreviousSibling(t)); } ret = Point.<N> inText(t, 0); } return ret; } }
private void getInnerTextOfNode(N node, StringBuilder builder) { T maybeText = document.asText(node); if (maybeText != null) { getInnerTextOfText(maybeText, builder); } else { getInnerTextOfElement(document.asElement(node), builder); } }
/** * Construct a point at the end of either an element or text node. * @param doc Document containing the node * @param node The node to get the start of * @return The Point.El end if node is an element, otherwise the position at the last text offset. */ public static <N, E extends N, T extends N> Point<N> textOrElementEnd( ReadableDocument<N,E,T> doc, N node) { E elt = doc.asElement(node); return elt == null ? inText(node, doc.getData(doc.asText(node)).length()) : end(node); }
T text = doc.asText(startNode); if (doc.isSameNode(startNode, endNode)) { return text == null ? "" : doc.getData(text).substring(startOffset, endOffset); text = doc.asText(node); if (text != null) { str.append(doc.getData(text)); text = doc.asText(node); if (text != null) { str.append(doc.getData(text).substring(0, endOffset));
/** * Checks whether a location has some text immediately to its left. * * @return true if text data precedes the given location */ public static <N, E extends N, T extends N> boolean textPrecedes( ReadableDocument<N, E, T> doc, LocationMapper<N> mapper, int location) { Point<N> point = mapper.locate(location); if (point.isInTextNode()) { return point.getTextOffset() > 0 || doc.asText(doc.getPreviousSibling(point.getContainer())) != null; } else { return doc.asText(Point.nodeBefore(doc, point.asElementPoint())) != null; } }
/** * Checks whether the current walk is a text node with the right data. * @throws IllegalStateException if the text node does not match the expected state. * @return the checked text node */ public T checkTextNode(String data) { Preconditions.checkState(nodeWalker.hasNext(), "Tree Walker: no more nodes to walk, text node expected"); progress(); T textNode = document.asText(currentNode); Preconditions.checkState(textNode != null, "Tree Walker: At element, text node expected"); Preconditions.checkState(document.getData(textNode).equals(data), "Tree Walker: Incorrect text node data"); return textNode; }
/** * Writes an entire subtree worth of operations to an initialization cursor. * NOTE(patcoleman): does not include annotations. * * @param doc Document the node resides within. * @param node Root of the subtree. * @param cursor Cursor to write results out to. */ public static <N, E extends N, T extends N> void buildDomInitializationFromSubtree( ReadableDocument<N, E, T> doc, N node, DocInitializationCursor cursor) { T text = doc.asText(node); if (text == null) { buildDomInitializationFromElement(doc, doc.asElement(node), cursor, true); } else { buildDomInitializationFromTextNode(doc, text, cursor); } }
/** * Appends a node to builder * * @param doc * @param node */ private <E extends N, T extends N> void appendNode( ReadableDocument<N, E, T> doc, N node) { E element = doc.asElement(node); if (element != null) { appendElement(doc, element); return; } T text = doc.asText(node); if (text != null) { appendText(doc, text); return; } assert(false); }
private static <N, E extends N, T extends N> Tx<N> findCharacterInNode( ReadableDocument<N, E, T> doc, Tx<N> start, CharacterLocator locator, boolean forward) { assert start.getContainer() != null && doc.asText(start.getContainer()) != null; String data = doc.getData(doc.asText(start.getContainer())); int index = locator.indexOf(data, start.getTextOffset(), forward); if (index != -1) { return Point.inText(start.getContainer(), index); } else { return null; } }
/** * Locates characters in contiguous of text nodes. * * Returns location when given locator matches with the data in a text node, * Returns null if not found. * * @param doc * @param start * @param locator * @param forward */ private static <N, E extends N, T extends N> Tx<N> locateCharacters( ReadableDocument<N, E, T> doc, Tx<N> start, CharacterLocator locator, boolean forward) { Tx<N> current = start; N node = start.getContainer(); Tx<N> found = null; while (true) { found = findCharacterInNode(doc, current.asTextPoint(), locator, forward); if (found != null) { return found; } node = forward ? doc.getNextSibling(node) : doc.getPreviousSibling(node); if (doc.asText(node) != null) { current = forward ? Point.inText(node, 0) : Point.inText(node, doc.getLength(doc.asText(node))); } else { return null; } } }
/** * Worker for appendNode * @param node * @return item length of node */ private int addNode(N node) { E element = view.asElement(node); if (element != null) { boolean selfClosing = isSelfClosing(element) && view.getFirstChild(element) == null; builder.append(startTag(element, selfClosing)); int len = 2; if (!selfClosing) { len += addChildXmlFragment(element); builder.append(endTag(element)); } return len; } else { String data = view.getData(view.asText(node)); return addText(permittedChars.coerceString(data)); } }
/** * Normalizes a point so that it is biased towards text nodes, and node ends * rather than node start. * * @param <N> * @param <E> * @param <T> * @param point * @param doc */ public static <N, E extends N, T extends N> Point<N> normalizePoint(Point<N> point, ReadableDocument<N, E, T> doc) { N previous = null; if (!point.isInTextNode()) { previous = Point.nodeBefore(doc, point.asElementPoint()); T nodeAfterAsText = doc.asText(point.getNodeAfter()); if (nodeAfterAsText != null) { point = Point.<N>inText(nodeAfterAsText, 0); } } else if (point.getTextOffset() == 0) { previous = doc.getPreviousSibling(point.getContainer()); } T previousAsText = doc.asText(previous); if (previous != null && previousAsText != null) { point = Point.inText(previous, doc.getLength(previousAsText)); } return point; }
/** Performs a walk against an iterable collection of nodes, returns true if all checks pass. */ public boolean checkWalk(ReadableDocument<N, E, T> doc, Iterable<N> nodes) { try { for (N node : nodes) { E elt = doc.asElement(node); if (elt != null) { checkElement(doc.getTagName(elt), doc.getAttributes(elt)); } else { checkTextNode(doc.getData(doc.asText(node))); } } return checkComplete(); } catch (IllegalStateException e) { return false; // assertion failed. } }
/** * Useful argument checking method for validating a point with respect * to a document * * @param doc * @param point * @param msgPrefix string to prepend to exception, if thrown */ public static <N, E extends N, T extends N> void checkPoint( ReadableDocument<N, E, T> doc, Point<N> point, String msgPrefix) { if (point.isInTextNode()) { checkOffset(doc, doc.asText(point.getContainer()), point.getTextOffset(), msgPrefix); } else { checkRelationship(doc, doc.asElement(point.getContainer()), point.getNodeAfter(), msgPrefix); } }
/** * Ensures the given point precedes a node, possibly splitting a text * node in order to do so, and possibly traversing until a node is found. * * @param point * @return a node at the same place as the input point, guaranteed to be at * a node boundary. If there is no node, the next available node. */ public static <N, T extends N> N ensureNodeBoundaryReturnNextNode(Point<N> point, ReadableDocument<N, ?, T> doc, TextNodeOrganiser<T> textNodeOrganiser) { Point.Tx<N> textStartPoint = point.asTextPoint(); if (textStartPoint != null) { T textNode = doc.asText(textStartPoint.getContainer()); N maybeSecond = textNodeOrganiser.splitText(textNode, textStartPoint.getTextOffset()); if (maybeSecond != null) { return maybeSecond; } else { return getNextNodeDepthFirst(doc, textNode, null, false); } } else if (point.getNodeAfter() != null) { return point.getNodeAfter(); } else { return getNextNodeDepthFirst(doc, point.getContainer(), null, false); } }
/** * 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(); } }