summaryrefslogtreecommitdiffstats
path: root/src/org/jsoup/select/StructuralEvaluator.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/jsoup/select/StructuralEvaluator.java')
-rw-r--r--src/org/jsoup/select/StructuralEvaluator.java132
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);
+ }
+ }
+}