diff options
Diffstat (limited to 'src/org/jsoup/select/StructuralEvaluator.java')
-rw-r--r-- | src/org/jsoup/select/StructuralEvaluator.java | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/org/jsoup/select/StructuralEvaluator.java b/src/org/jsoup/select/StructuralEvaluator.java new file mode 100644 index 0000000000..69e8a62e58 --- /dev/null +++ b/src/org/jsoup/select/StructuralEvaluator.java @@ -0,0 +1,132 @@ +package org.jsoup.select; + +import org.jsoup.nodes.Element; + +/** + * Base structural evaluator. + */ +abstract class StructuralEvaluator extends Evaluator { + Evaluator evaluator; + + static class Root extends Evaluator { + public boolean matches(Element root, Element element) { + return root == element; + } + } + + static class Has extends StructuralEvaluator { + public Has(Evaluator evaluator) { + this.evaluator = evaluator; + } + + public boolean matches(Element root, Element element) { + for (Element e : element.getAllElements()) { + if (e != element && evaluator.matches(root, e)) + return true; + } + return false; + } + + public String toString() { + return String.format(":has(%s)", evaluator); + } + } + + static class Not extends StructuralEvaluator { + public Not(Evaluator evaluator) { + this.evaluator = evaluator; + } + + public boolean matches(Element root, Element node) { + return !evaluator.matches(root, node); + } + + public String toString() { + return String.format(":not%s", evaluator); + } + } + + static class Parent extends StructuralEvaluator { + public Parent(Evaluator evaluator) { + this.evaluator = evaluator; + } + + public boolean matches(Element root, Element element) { + if (root == element) + return false; + + Element parent = element.parent(); + while (parent != root) { + if (evaluator.matches(root, parent)) + return true; + parent = parent.parent(); + } + return false; + } + + public String toString() { + return String.format(":parent%s", evaluator); + } + } + + static class ImmediateParent extends StructuralEvaluator { + public ImmediateParent(Evaluator evaluator) { + this.evaluator = evaluator; + } + + public boolean matches(Element root, Element element) { + if (root == element) + return false; + + Element parent = element.parent(); + return parent != null && evaluator.matches(root, parent); + } + + public String toString() { + return String.format(":ImmediateParent%s", evaluator); + } + } + + static class PreviousSibling extends StructuralEvaluator { + public PreviousSibling(Evaluator evaluator) { + this.evaluator = evaluator; + } + + public boolean matches(Element root, Element element) { + if (root == element) + return false; + + Element prev = element.previousElementSibling(); + + while (prev != null) { + if (evaluator.matches(root, prev)) + return true; + + prev = prev.previousElementSibling(); + } + return false; + } + + public String toString() { + return String.format(":prev*%s", evaluator); + } + } + + static class ImmediatePreviousSibling extends StructuralEvaluator { + public ImmediatePreviousSibling(Evaluator evaluator) { + this.evaluator = evaluator; + } + + public boolean matches(Element root, Element element) { + if (root == element) + return false; + + Element prev = element.previousElementSibling(); + return prev != null && evaluator.matches(root, prev); + } + + public String toString() { + return String.format(":prev%s", evaluator); + } + } +} |