diff options
author | Leif Åstrand <leif@vaadin.com> | 2012-09-05 19:50:56 +0300 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2012-09-05 19:51:15 +0300 |
commit | 7d25670284b11c7c62ba25183f265227cb3dba83 (patch) | |
tree | c8e76eb70dd3cdd5cf59a99419635f2188b25c24 /server/src/org/jsoup/nodes/Node.java | |
parent | 1d0c96de9595c243d88471476d21e5f248be63f7 (diff) | |
download | vaadin-framework-7d25670284b11c7c62ba25183f265227cb3dba83.tar.gz vaadin-framework-7d25670284b11c7c62ba25183f265227cb3dba83.zip |
Reformat project
Diffstat (limited to 'server/src/org/jsoup/nodes/Node.java')
-rw-r--r-- | server/src/org/jsoup/nodes/Node.java | 402 |
1 files changed, 257 insertions, 145 deletions
diff --git a/server/src/org/jsoup/nodes/Node.java b/server/src/org/jsoup/nodes/Node.java index eb2b40ee73..72b8dcbd47 100644 --- a/server/src/org/jsoup/nodes/Node.java +++ b/server/src/org/jsoup/nodes/Node.java @@ -1,21 +1,23 @@ package org.jsoup.nodes; -import org.jsoup.helper.StringUtil; -import org.jsoup.helper.Validate; -import org.jsoup.parser.Parser; -import org.jsoup.select.NodeTraversor; -import org.jsoup.select.NodeVisitor; - import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.List; -/** - The base, abstract Node model. Elements, Documents, Comments etc are all Node instances. +import org.jsoup.helper.StringUtil; +import org.jsoup.helper.Validate; +import org.jsoup.parser.Parser; +import org.jsoup.select.NodeTraversor; +import org.jsoup.select.NodeVisitor; - @author Jonathan Hedley, jonathan@hedley.net */ +/** + * The base, abstract Node model. Elements, Documents, Comments etc are all Node + * instances. + * + * @author Jonathan Hedley, jonathan@hedley.net + */ public abstract class Node implements Cloneable { Node parentNode; List<Node> childNodes; @@ -24,14 +26,17 @@ public abstract class Node implements Cloneable { int siblingIndex; /** - Create a new Node. - @param baseUri base URI - @param attributes attributes (not null, but may be empty) + * Create a new Node. + * + * @param baseUri + * base URI + * @param attributes + * attributes (not null, but may be empty) */ protected Node(String baseUri, Attributes attributes) { Validate.notNull(baseUri); Validate.notNull(attributes); - + childNodes = new ArrayList<Node>(4); this.baseUri = baseUri.trim(); this.attributes = attributes; @@ -42,7 +47,8 @@ public abstract class Node implements Cloneable { } /** - * Default constructor. Doesn't setup base uri, children, or attributes; use with caution. + * Default constructor. Doesn't setup base uri, children, or attributes; use + * with caution. */ protected Node() { childNodes = Collections.emptyList(); @@ -50,18 +56,23 @@ public abstract class Node implements Cloneable { } /** - Get the node name of this node. Use for debugging purposes and not logic switching (for that, use instanceof). - @return node name + * Get the node name of this node. Use for debugging purposes and not logic + * switching (for that, use instanceof). + * + * @return node name */ public abstract String nodeName(); /** * Get an attribute's value by its key. * <p/> - * To get an absolute URL from an attribute that may be a relative URL, prefix the key with <code><b>abs</b></code>, - * which is a shortcut to the {@link #absUrl} method. - * E.g.: <blockquote><code>String url = a.attr("abs:href");</code></blockquote> - * @param attributeKey The attribute key. + * To get an absolute URL from an attribute that may be a relative URL, + * prefix the key with <code><b>abs</b></code>, which is a shortcut to the + * {@link #absUrl} method. E.g.: <blockquote> + * <code>String url = a.attr("abs:href");</code></blockquote> + * + * @param attributeKey + * The attribute key. * @return The attribute, or empty string if not present (to avoid nulls). * @see #attributes() * @see #hasAttr(String) @@ -70,25 +81,33 @@ public abstract class Node implements Cloneable { public String attr(String attributeKey) { Validate.notNull(attributeKey); - if (attributes.hasKey(attributeKey)) + if (attributes.hasKey(attributeKey)) { return attributes.get(attributeKey); - else if (attributeKey.toLowerCase().startsWith("abs:")) + } else if (attributeKey.toLowerCase().startsWith("abs:")) { return absUrl(attributeKey.substring("abs:".length())); - else return ""; + } else { + return ""; + } } /** * Get all of the element's attributes. - * @return attributes (which implements iterable, in same order as presented in original HTML). + * + * @return attributes (which implements iterable, in same order as presented + * in original HTML). */ public Attributes attributes() { return attributes; } /** - * Set an attribute (key=value). If the attribute already exists, it is replaced. - * @param attributeKey The attribute key. - * @param attributeValue The attribute value. + * Set an attribute (key=value). If the attribute already exists, it is + * replaced. + * + * @param attributeKey + * The attribute key. + * @param attributeValue + * The attribute value. * @return this (for chaining) */ public Node attr(String attributeKey, String attributeValue) { @@ -98,7 +117,9 @@ public abstract class Node implements Cloneable { /** * Test if this element has an attribute. - * @param attributeKey The attribute key to check. + * + * @param attributeKey + * The attribute key to check. * @return true if the attribute exists, false if not. */ public boolean hasAttr(String attributeKey) { @@ -106,15 +127,18 @@ public abstract class Node implements Cloneable { if (attributeKey.toLowerCase().startsWith("abs:")) { String key = attributeKey.substring("abs:".length()); - if (attributes.hasKey(key) && !absUrl(key).equals("")) + if (attributes.hasKey(key) && !absUrl(key).equals("")) { return true; + } } return attributes.hasKey(attributeKey); } /** * Remove an attribute from this element. - * @param attributeKey The attribute to remove. + * + * @param attributeKey + * The attribute to remove. * @return this (for chaining) */ public Node removeAttr(String attributeKey) { @@ -124,47 +148,56 @@ public abstract class Node implements Cloneable { } /** - Get the base URI of this node. - @return base URI + * Get the base URI of this node. + * + * @return base URI */ public String baseUri() { return baseUri; } /** - Update the base URI of this node and all of its descendants. - @param baseUri base URI to set + * Update the base URI of this node and all of its descendants. + * + * @param baseUri + * base URI to set */ public void setBaseUri(final String baseUri) { Validate.notNull(baseUri); traverse(new NodeVisitor() { + @Override public void head(Node node, int depth) { node.baseUri = baseUri; } + @Override public void tail(Node node, int depth) { } }); } /** - * Get an absolute URL from a URL attribute that may be relative (i.e. an <code><a href></code> or - * <code><img src></code>). + * Get an absolute URL from a URL attribute that may be relative (i.e. an + * <code><a href></code> or <code><img src></code>). * <p/> * E.g.: <code>String absUrl = linkEl.absUrl("href");</code> * <p/> - * If the attribute value is already absolute (i.e. it starts with a protocol, like - * <code>http://</code> or <code>https://</code> etc), and it successfully parses as a URL, the attribute is - * returned directly. Otherwise, it is treated as a URL relative to the element's {@link #baseUri}, and made - * absolute using that. + * If the attribute value is already absolute (i.e. it starts with a + * protocol, like <code>http://</code> or <code>https://</code> etc), and it + * successfully parses as a URL, the attribute is returned directly. + * Otherwise, it is treated as a URL relative to the element's + * {@link #baseUri}, and made absolute using that. * <p/> - * As an alternate, you can use the {@link #attr} method with the <code>abs:</code> prefix, e.g.: + * As an alternate, you can use the {@link #attr} method with the + * <code>abs:</code> prefix, e.g.: * <code>String absUrl = linkEl.attr("abs:href");</code> - * - * @param attributeKey The attribute key - * @return An absolute URL if one could be made, or an empty string (not null) if the attribute was missing or - * could not be made successfully into a URL. + * + * @param attributeKey + * The attribute key + * @return An absolute URL if one could be made, or an empty string (not + * null) if the attribute was missing or could not be made + * successfully into a URL. * @see #attr * @see java.net.URL#URL(java.net.URL, String) */ @@ -180,13 +213,16 @@ public abstract class Node implements Cloneable { try { base = new URL(baseUri); } catch (MalformedURLException e) { - // the base is unsuitable, but the attribute may be abs on its own, so try that + // the base is unsuitable, but the attribute may be abs on + // its own, so try that URL abs = new URL(relUrl); return abs.toExternalForm(); } - // workaround: java resolves '//path/file + ?foo' to '//path/?foo', not '//path/file?foo' as desired - if (relUrl.startsWith("?")) + // workaround: java resolves '//path/file + ?foo' to + // '//path/?foo', not '//path/file?foo' as desired + if (relUrl.startsWith("?")) { relUrl = base.getPath() + relUrl; + } URL abs = new URL(base, relUrl); return abs.toExternalForm(); } catch (MalformedURLException e) { @@ -196,50 +232,58 @@ public abstract class Node implements Cloneable { } /** - Get a child node by index - @param index index of child node - @return the child node at this index. + * Get a child node by index + * + * @param index + * index of child node + * @return the child node at this index. */ public Node childNode(int index) { return childNodes.get(index); } /** - Get this node's children. Presented as an unmodifiable list: new children can not be added, but the child nodes - themselves can be manipulated. - @return list of children. If no children, returns an empty list. + * Get this node's children. Presented as an unmodifiable list: new children + * can not be added, but the child nodes themselves can be manipulated. + * + * @return list of children. If no children, returns an empty list. */ public List<Node> childNodes() { return Collections.unmodifiableList(childNodes); } - + protected Node[] childNodesAsArray() { return childNodes.toArray(new Node[childNodes().size()]); } /** - Gets this node's parent node. - @return parent node; or null if no parent. + * Gets this node's parent node. + * + * @return parent node; or null if no parent. */ public Node parent() { return parentNode; } - + /** - * Gets the Document associated with this Node. - * @return the Document associated with this Node, or null if there is no such Document. + * Gets the Document associated with this Node. + * + * @return the Document associated with this Node, or null if there is no + * such Document. */ public Document ownerDocument() { - if (this instanceof Document) + if (this instanceof Document) { return (Document) this; - else if (parentNode == null) + } else if (parentNode == null) { return null; - else + } else { return parentNode.ownerDocument(); + } } - + /** - * Remove (delete) this node from the DOM tree. If this node has children, they are also removed. + * Remove (delete) this node from the DOM tree. If this node has children, + * they are also removed. */ public void remove() { Validate.notNull(parentNode); @@ -247,8 +291,11 @@ public abstract class Node implements Cloneable { } /** - * Insert the specified HTML into the DOM before this node (i.e. as a preceding sibling). - * @param html HTML to add before this node + * Insert the specified HTML into the DOM before this node (i.e. as a + * preceding sibling). + * + * @param html + * HTML to add before this node * @return this node, for chaining * @see #after(String) */ @@ -258,8 +305,11 @@ public abstract class Node implements Cloneable { } /** - * Insert the specified node into the DOM before this node (i.e. as a preceding sibling). - * @param node to add before this node + * Insert the specified node into the DOM before this node (i.e. as a + * preceding sibling). + * + * @param node + * to add before this node * @return this node, for chaining * @see #after(Node) */ @@ -272,19 +322,25 @@ public abstract class Node implements Cloneable { } /** - * Insert the specified HTML into the DOM after this node (i.e. as a following sibling). - * @param html HTML to add after this node + * Insert the specified HTML into the DOM after this node (i.e. as a + * following sibling). + * + * @param html + * HTML to add after this node * @return this node, for chaining * @see #before(String) */ public Node after(String html) { - addSiblingHtml(siblingIndex()+1, html); + addSiblingHtml(siblingIndex() + 1, html); return this; } /** - * Insert the specified node into the DOM after this node (i.e. as a following sibling). - * @param node to add after this node + * Insert the specified node into the DOM after this node (i.e. as a + * following sibling). + * + * @param node + * to add after this node * @return this node, for chaining * @see #before(Node) */ @@ -292,7 +348,7 @@ public abstract class Node implements Cloneable { Validate.notNull(node); Validate.notNull(parentNode); - parentNode.addChildren(siblingIndex()+1, node); + parentNode.addChildren(siblingIndex() + 1, node); return this; } @@ -300,31 +356,39 @@ public abstract class Node implements Cloneable { Validate.notNull(html); Validate.notNull(parentNode); - Element context = parent() instanceof Element ? (Element) parent() : null; + Element context = parent() instanceof Element ? (Element) parent() + : null; List<Node> nodes = Parser.parseFragment(html, context, baseUri()); parentNode.addChildren(index, nodes.toArray(new Node[nodes.size()])); } /** - Wrap the supplied HTML around this node. - @param html HTML to wrap around this element, e.g. {@code <div class="head"></div>}. Can be arbitrarily deep. - @return this node, for chaining. + * Wrap the supplied HTML around this node. + * + * @param html + * HTML to wrap around this element, e.g. + * {@code <div class="head"></div>}. Can be arbitrarily deep. + * @return this node, for chaining. */ public Node wrap(String html) { Validate.notEmpty(html); - Element context = parent() instanceof Element ? (Element) parent() : null; - List<Node> wrapChildren = Parser.parseFragment(html, context, baseUri()); + Element context = parent() instanceof Element ? (Element) parent() + : null; + List<Node> wrapChildren = Parser + .parseFragment(html, context, baseUri()); Node wrapNode = wrapChildren.get(0); - if (wrapNode == null || !(wrapNode instanceof Element)) // nothing to wrap with; noop + if (wrapNode == null || !(wrapNode instanceof Element)) { return null; + } Element wrap = (Element) wrapNode; Element deepest = getDeepChild(wrap); parentNode.replaceChild(this, wrap); deepest.addChildren(this); - // remainder (unbalanced wrap, like <div></div><p></p> -- The <p> is remainder + // remainder (unbalanced wrap, like <div></div><p></p> -- The <p> is + // remainder if (wrapChildren.size() > 0) { for (int i = 0; i < wrapChildren.size(); i++) { Node remainder = wrapChildren.get(i); @@ -336,15 +400,19 @@ public abstract class Node implements Cloneable { } /** - * Removes this node from the DOM, and moves its children up into the node's parent. This has the effect of dropping - * the node but keeping its children. + * Removes this node from the DOM, and moves its children up into the node's + * parent. This has the effect of dropping the node but keeping its + * children. * <p/> * For example, with the input html:<br/> * {@code <div>One <span>Two <b>Three</b></span></div>}<br/> - * Calling {@code element.unwrap()} on the {@code span} element will result in the html:<br/> + * Calling {@code element.unwrap()} on the {@code span} element will result + * in the html:<br/> * {@code <div>One Two <b>Three</b></div>}<br/> * and the {@code "Two "} {@link TextNode} being returned. - * @return the first child of this node, after the node has been unwrapped. Null if the node had no children. + * + * @return the first child of this node, after the node has been unwrapped. + * Null if the node had no children. * @see #remove() * @see #wrap(String) */ @@ -353,23 +421,26 @@ public abstract class Node implements Cloneable { int index = siblingIndex; Node firstChild = childNodes.size() > 0 ? childNodes.get(0) : null; - parentNode.addChildren(index, this.childNodesAsArray()); - this.remove(); + parentNode.addChildren(index, childNodesAsArray()); + remove(); return firstChild; } private Element getDeepChild(Element el) { List<Element> children = el.children(); - if (children.size() > 0) + if (children.size() > 0) { return getDeepChild(children.get(0)); - else + } else { return el; + } } - + /** * Replace this node in the DOM with the supplied node. - * @param in the node that will will replace the existing node. + * + * @param in + * the node that will will replace the existing node. */ public void replaceWith(Node in) { Validate.notNull(in); @@ -378,17 +449,19 @@ public abstract class Node implements Cloneable { } protected void setParentNode(Node parentNode) { - if (this.parentNode != null) + if (this.parentNode != null) { this.parentNode.removeChild(this); + } this.parentNode = parentNode; } protected void replaceChild(Node out, Node in) { Validate.isTrue(out.parentNode == this); Validate.notNull(in); - if (in.parentNode != null) + if (in.parentNode != null) { in.parentNode.removeChild(in); - + } + Integer index = out.siblingIndex(); childNodes.set(index, in); in.parentNode = this; @@ -405,11 +478,12 @@ public abstract class Node implements Cloneable { } protected void addChildren(Node... children) { - //most used. short circuit addChildren(int), which hits reindex children and array copy - for (Node child: children) { + // most used. short circuit addChildren(int), which hits reindex + // children and array copy + for (Node child : children) { reparentChild(child); childNodes.add(child); - child.setSiblingIndex(childNodes.size()-1); + child.setSiblingIndex(childNodes.size() - 1); } } @@ -424,85 +498,100 @@ public abstract class Node implements Cloneable { } private void reparentChild(Node child) { - if (child.parentNode != null) + if (child.parentNode != null) { child.parentNode.removeChild(child); + } child.setParentNode(this); } - + private void reindexChildren() { for (int i = 0; i < childNodes.size(); i++) { childNodes.get(i).setSiblingIndex(i); } } - + /** - Retrieves this node's sibling nodes. Similar to {@link #childNodes() node.parent.childNodes()}, but does not - include this node (a node is not a sibling of itself). - @return node siblings. If the node has no parent, returns an empty list. + * Retrieves this node's sibling nodes. Similar to {@link #childNodes() + * node.parent.childNodes()}, but does not include this node (a node is not + * a sibling of itself). + * + * @return node siblings. If the node has no parent, returns an empty list. */ public List<Node> siblingNodes() { - if (parentNode == null) + if (parentNode == null) { return Collections.emptyList(); + } List<Node> nodes = parentNode.childNodes; List<Node> siblings = new ArrayList<Node>(nodes.size() - 1); - for (Node node: nodes) - if (node != this) + for (Node node : nodes) { + if (node != this) { siblings.add(node); + } + } return siblings; } /** - Get this node's next sibling. - @return next sibling, or null if this is the last sibling + * Get this node's next sibling. + * + * @return next sibling, or null if this is the last sibling */ public Node nextSibling() { - if (parentNode == null) + if (parentNode == null) { return null; // root - + } + List<Node> siblings = parentNode.childNodes; Integer index = siblingIndex(); Validate.notNull(index); - if (siblings.size() > index+1) - return siblings.get(index+1); - else + if (siblings.size() > index + 1) { + return siblings.get(index + 1); + } else { return null; + } } /** - Get this node's previous sibling. - @return the previous sibling, or null if this is the first sibling + * Get this node's previous sibling. + * + * @return the previous sibling, or null if this is the first sibling */ public Node previousSibling() { - if (parentNode == null) + if (parentNode == null) { return null; // root + } List<Node> siblings = parentNode.childNodes; Integer index = siblingIndex(); Validate.notNull(index); - if (index > 0) - return siblings.get(index-1); - else + if (index > 0) { + return siblings.get(index - 1); + } else { return null; + } } /** - * Get the list index of this node in its node sibling list. I.e. if this is the first node - * sibling, returns 0. + * Get the list index of this node in its node sibling list. I.e. if this is + * the first node sibling, returns 0. + * * @return position in node sibling list * @see org.jsoup.nodes.Element#elementSiblingIndex() */ public int siblingIndex() { return siblingIndex; } - + protected void setSiblingIndex(int siblingIndex) { this.siblingIndex = siblingIndex; } /** * Perform a depth-first traversal through this node and its descendants. - * @param nodeVisitor the visitor callbacks to perform on each node + * + * @param nodeVisitor + * the visitor callbacks to perform on each node * @return this node, for chaining */ public Node traverse(NodeVisitor nodeVisitor) { @@ -513,8 +602,9 @@ public abstract class Node implements Cloneable { } /** - Get the outer HTML of this node. - @return HTML + * Get the outer HTML of this node. + * + * @return HTML */ public String outerHtml() { StringBuilder accum = new StringBuilder(128); @@ -523,34 +613,47 @@ public abstract class Node implements Cloneable { } protected void outerHtml(StringBuilder accum) { - new NodeTraversor(new OuterHtmlVisitor(accum, getOutputSettings())).traverse(this); + new NodeTraversor(new OuterHtmlVisitor(accum, getOutputSettings())) + .traverse(this); } - // if this node has no document (or parent), retrieve the default output settings + // if this node has no document (or parent), retrieve the default output + // settings private Document.OutputSettings getOutputSettings() { - return ownerDocument() != null ? ownerDocument().outputSettings() : (new Document("")).outputSettings(); + return ownerDocument() != null ? ownerDocument().outputSettings() + : (new Document("")).outputSettings(); } /** - Get the outer HTML of this node. - @param accum accumulator to place HTML into + * Get the outer HTML of this node. + * + * @param accum + * accumulator to place HTML into */ - abstract void outerHtmlHead(StringBuilder accum, int depth, Document.OutputSettings out); + abstract void outerHtmlHead(StringBuilder accum, int depth, + Document.OutputSettings out); - abstract void outerHtmlTail(StringBuilder accum, int depth, Document.OutputSettings out); + abstract void outerHtmlTail(StringBuilder accum, int depth, + Document.OutputSettings out); + @Override public String toString() { return outerHtml(); } - protected void indent(StringBuilder accum, int depth, Document.OutputSettings out) { - accum.append("\n").append(StringUtil.padding(depth * out.indentAmount())); + protected void indent(StringBuilder accum, int depth, + Document.OutputSettings out) { + accum.append("\n").append( + StringUtil.padding(depth * out.indentAmount())); } @Override public boolean equals(Object o) { - if (this == o) return true; - // todo: have nodes hold a child index, compare against that and parent (not children) + if (this == o) { + return true; + } + // todo: have nodes hold a child index, compare against that and parent + // (not children) return false; } @@ -563,11 +666,14 @@ public abstract class Node implements Cloneable { } /** - * Create a stand-alone, deep copy of this node, and all of its children. The cloned node will have no siblings or - * parent node. As a stand-alone object, any changes made to the clone or any of its children will not impact the - * original node. + * Create a stand-alone, deep copy of this node, and all of its children. + * The cloned node will have no siblings or parent node. As a stand-alone + * object, any changes made to the clone or any of its children will not + * impact the original node. * <p> - * The cloned node may be adopted into another Document or node structure using {@link Element#appendChild(Node)}. + * The cloned node may be adopted into another Document or node structure + * using {@link Element#appendChild(Node)}. + * * @return stand-alone cloned node */ @Override @@ -588,8 +694,11 @@ public abstract class Node implements Cloneable { clone.attributes = attributes != null ? attributes.clone() : null; clone.baseUri = baseUri; clone.childNodes = new ArrayList<Node>(childNodes.size()); - for (Node child: childNodes) - clone.childNodes.add(child.doClone(clone)); // clone() creates orphans, doClone() keeps parent + for (Node child : childNodes) { + clone.childNodes.add(child.doClone(clone)); // clone() creates + // orphans, doClone() + // keeps parent + } return clone; } @@ -603,13 +712,16 @@ public abstract class Node implements Cloneable { this.out = out; } + @Override public void head(Node node, int depth) { node.outerHtmlHead(accum, depth, out); } + @Override public void tail(Node node, int depth) { - if (!node.nodeName().equals("#text")) // saves a void hit. + if (!node.nodeName().equals("#text")) { node.outerHtmlTail(accum, depth, out); + } } } } |