diff --git a/json-path/src/main/java/com/jayway/jsonpath/Criteria.java b/json-path/src/main/java/com/jayway/jsonpath/Criteria.java
index d634a2a4..44d28159 100755
--- a/json-path/src/main/java/com/jayway/jsonpath/Criteria.java
+++ b/json-path/src/main/java/com/jayway/jsonpath/Criteria.java
@@ -157,6 +157,94 @@ public class Criteria implements Predicate {
return this;
}
+ /**
+ * Creates a criterion using the <all; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria ltall(Object... o) {
+ return ltall(Arrays.asList(o));
+ }
+
+ /**
+ * Creates a criterion using the <all; operator
+ *
+ * @param c
+ * @return the criteria
+ */
+ public Criteria ltall(Collection> c) {
+ this.criteriaType = RelationalOperator.LTALL;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the <eall; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria lteall(Object... o) {
+ return lteall(Arrays.asList(o));
+ }
+
+ /**
+ * Creates a criterion using the <eall; operator
+ *
+ * @param c
+ * @return the criteria
+ */
+ public Criteria lteall(Collection> c) {
+ this.criteriaType = RelationalOperator.LTEALL;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the <any; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria ltany(Object... o) {
+ return ltany(Arrays.asList(o));
+ }
+
+ /**
+ * Creates a criterion using the <any; operator
+ *
+ * @param c
+ * @return the criteria
+ */
+ public Criteria ltany(Collection> c) {
+ this.criteriaType = RelationalOperator.LTANY;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the <eany; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria lteany(Object... o) {
+ return lteany(Arrays.asList(o));
+ }
+
+ /**
+ * Creates a criterion using the <eany; operator
+ *
+ * @param c
+ * @return the criteria
+ */
+ public Criteria lteany(Collection> c) {
+ this.criteriaType = RelationalOperator.LTEANY;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
/**
* Creates a criterion using the <= operator
*
@@ -181,6 +269,94 @@ public class Criteria implements Predicate {
return this;
}
+ /**
+ * Creates a criterion using the >all; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria gtall(Object... o) {
+ return gtall(Arrays.asList(o));
+ }
+
+ /**
+ * Creates a criterion using the >all; operator
+ *
+ * @param c
+ * @return the criteria
+ */
+ public Criteria gtall(Collection> c) {
+ this.criteriaType = RelationalOperator.GTALL;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the >eall; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria gteall(Object... o) {
+ return gteall(Arrays.asList(o));
+ }
+
+ /**
+ * Creates a criterion using the >eall; operator
+ *
+ * @param c
+ * @return the criteria
+ */
+ public Criteria gteall(Collection> c) {
+ this.criteriaType = RelationalOperator.GTEALL;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the >any; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria gtany(Object... o) {
+ return gtany(Arrays.asList(o));
+ }
+
+ /**
+ * Creates a criterion using the >any; operator
+ *
+ * @param c
+ * @return the criteria
+ */
+ public Criteria gtany(Collection> c) {
+ this.criteriaType = RelationalOperator.GTANY;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the >eany; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria gteany(Object... o) {
+ return gteany(Arrays.asList(o));
+ }
+
+ /**
+ * Creates a criterion using the >eany; operator
+ *
+ * @param c
+ * @return the criteria
+ */
+ public Criteria gteany(Collection> c) {
+ this.criteriaType = RelationalOperator.GTEANY;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
/**
* Creates a criterion using the >= operator
*
@@ -304,7 +480,7 @@ public class Criteria implements Predicate {
* @return the criteria
*/
public Criteria anyof(Object... o) {
- return subsetof(Arrays.asList(o));
+ return anyof(Arrays.asList(o));
}
/**
@@ -371,6 +547,371 @@ public class Criteria implements Predicate {
return this;
}
+ /**
+ * Creates a criterion using the &dateeq; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria dateeq(Object o) {
+ this.criteriaType = RelationalOperator.DATEEQ;
+ this.right = ValueNode.toValueNode(o);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &dayeq; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria dayeq(Object o) {
+ this.criteriaType = RelationalOperator.DAYEQ;
+ this.right = ValueNode.toValueNode(o);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &montheq; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria montheq(Object o) {
+ this.criteriaType = RelationalOperator.MONTHEQ;
+ this.right = ValueNode.toValueNode(o);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &yeareq; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria yeareq(Object o) {
+ this.criteriaType = RelationalOperator.YEAREQ;
+ this.right = ValueNode.toValueNode(o);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &dayin; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria dayin(Object... o) {
+ return dayin(Arrays.asList(o));
+ }
+
+ /**
+ * Creates a criterion using the &dayin; operator
+ *
+ * @param c
+ * @return the criteria
+ */
+ public Criteria dayin(Collection> c) {
+ this.criteriaType = RelationalOperator.DAYIN;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &monthin; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria monthin(Object... o) {
+ return monthin(Arrays.asList(o));
+ }
+
+ /**
+ * Creates a criterion using the &monthin; operator
+ *
+ * @param c
+ * @return the criteria
+ */
+ public Criteria monthin(Collection> c) {
+ this.criteriaType = RelationalOperator.MONTHIN;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &yearin; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria yearin(Object... o) {
+ return yearin(Arrays.asList(o));
+ }
+
+ /**
+ * Creates a criterion using the &yearin; operator
+ *
+ * @param c
+ * @return the criteria
+ */
+ public Criteria yearin(Collection> c) {
+ this.criteriaType = RelationalOperator.YEARIN;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &before; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria before(Object o) {
+ this.criteriaType = RelationalOperator.BEFORE;
+ this.right = ValueNode.toValueNode(o);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &after; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria after(Object o) {
+ this.criteriaType = RelationalOperator.AFTER;
+ this.right = ValueNode.toValueNode(o);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &houreq; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria houreq(Object o) {
+ this.criteriaType = RelationalOperator.HOUREQ;
+ this.right = ValueNode.toValueNode(o);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &hourin; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria hourin(Object... o) {
+ return hourin(Arrays.asList(o));
+ }
+
+ /**
+ * Creates a criterion using the &hourin; operator
+ *
+ * @param c
+ * @return the criteria
+ */
+ public Criteria hourin(Collection> c) {
+ this.criteriaType = RelationalOperator.HOURIN;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &timebefore; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria timebefore(Object o) {
+ this.criteriaType = RelationalOperator.TIMEBEFORE;
+ this.right = ValueNode.toValueNode(o);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &timeafter; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria timeafter(Object o) {
+ this.criteriaType = RelationalOperator.TIMEAFTER;
+ this.right = ValueNode.toValueNode(o);
+ return this;
+ }
+
+ /**
+ * The allmatch
operator selects objects for which the specified field is
+ * an array whose elements comprise a subset of the set comprised by the elements of
+ * the specified array.
+ *
+ * @param o the values to match against
+ * @return the criteria
+ */
+ public Criteria allmatch(Object... o) {
+ return allmatch(Arrays.asList(o));
+ }
+
+ /**
+ * The allmatch
operator selects objects for which the specified field is
+ * an array whose elements comprise a subset of the set comprised by the elements of
+ * the specified array.
+ *
+ * @param c the values to match against
+ * @return the criteria
+ */
+ public Criteria allmatch(Collection> c) {
+ notNull(c, "collection can not be null");
+ this.criteriaType = RelationalOperator.ALLMATCH;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
+ /**
+ * The anymatch
operator selects objects for which the specified field is
+ * an array whose elements comprise a subset of the set comprised by the elements of
+ * the specified array.
+ *
+ * @param o the values to match against
+ * @return the criteria
+ */
+ public Criteria anymatch(Object... o) {
+ return anymatch(Arrays.asList(o));
+ }
+
+ /**
+ * The anymatch
operator selects objects for which the specified field is
+ * an array whose elements comprise a subset of the set comprised by the elements of
+ * the specified array.
+ *
+ * @param c the values to match against
+ * @return the criteria
+ */
+ public Criteria anymatch(Collection> c) {
+ notNull(c, "collection can not be null");
+ this.criteriaType = RelationalOperator.ANYMATCH;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
+ /**
+ * The nonematch
operator selects objects for which the specified field is
+ * an array whose elements comprise a subset of the set comprised by the elements of
+ * the specified array.
+ *
+ * @param o the values to match against
+ * @return the criteria
+ */
+ public Criteria nonematch(Object... o) {
+ return nonematch(Arrays.asList(o));
+ }
+
+ /**
+ * The nonematch
operator selects objects for which the specified field is
+ * an array whose elements comprise a subset of the set comprised by the elements of
+ * the specified array.
+ *
+ * @param c the values to match against
+ * @return the criteria
+ */
+ public Criteria nonematch(Collection> c) {
+ notNull(c, "collection can not be null");
+ this.criteriaType = RelationalOperator.NONEMATCH;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
+ /**
+ * The exactmatch
operator selects objects for which the specified field is
+ * an array whose elements comprise a subset of the set comprised by the elements of
+ * the specified array.
+ *
+ * @param o the values to match against
+ * @return the criteria
+ */
+ public Criteria exactmatch(Object... o) {
+ return exactmatch(Arrays.asList(o));
+ }
+
+ /**
+ * The exactmatch
operator selects objects for which the specified field is
+ * an array whose elements comprise a subset of the set comprised by the elements of
+ * the specified array.
+ *
+ * @param c the values to match against
+ * @return the criteria
+ */
+ public Criteria exactmatch(Collection> c) {
+ notNull(c, "collection can not be null");
+ this.criteriaType = RelationalOperator.EXACTMATCH;
+ this.right = new ValueListNode(c);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &windowin; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria windowin(Object o) {
+ this.criteriaType = RelationalOperator.WINDOWIN;
+ this.right = ValueNode.toValueNode(o);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &windowout; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria windowout(Object o) {
+ this.criteriaType = RelationalOperator.WINDOWOUT;
+ this.right = ValueNode.toValueNode(o);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &windowtimein; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria windowtimein(Object o) {
+ this.criteriaType = RelationalOperator.WINDOWTIMEIN;
+ this.right = ValueNode.toValueNode(o);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the &windowtimeout; operator
+ *
+ * @param o
+ * @return the criteria
+ */
+ public Criteria windowtimeout(Object o) {
+ this.criteriaType = RelationalOperator.WINDOWTIMEOUT;
+ this.right = ValueNode.toValueNode(o);
+ return this;
+ }
+
+ /**
+ * The notcontains
operator asserts that the provided object is not contained
+ * in the result. The object that should contain the input can be either an object or a String.
+ *
+ * @param o that should not exists in given collection or
+ * @return the criteria
+ */
+ public Criteria notcontains(Object o) {
+ this.criteriaType = RelationalOperator.NOTCONTAINS;
+ this.right = ValueNode.toValueNode(o);
+ return this;
+ }
+
/**
* The size
operator matches:
*
diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java
index 0ee59c72..040cf8ac 100755
--- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java
+++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java
@@ -1,8 +1,16 @@
package com.jayway.jsonpath.internal.filter;
+import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.JsonPathException;
import com.jayway.jsonpath.Predicate;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.Month;
+import java.time.ZonedDateTime;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
@@ -35,16 +43,46 @@ public class EvaluatorFactory {
evaluators.put(RelationalOperator.SUBSETOF, new SubsetOfEvaluator());
evaluators.put(RelationalOperator.ANYOF, new AnyOfEvaluator());
evaluators.put(RelationalOperator.NONEOF, new NoneOfEvaluator());
+ evaluators.put(RelationalOperator.GTALL, new GreaterThanAllEvaluator());
+ evaluators.put(RelationalOperator.GTEALL, new GreaterThanEqualsAllEvaluator());
+ evaluators.put(RelationalOperator.GTANY, new GreaterThanAnyEvaluator());
+ evaluators.put(RelationalOperator.GTEANY, new GreaterThanEqualsAnyEvaluator());
+ evaluators.put(RelationalOperator.LTALL, new LessThanAllEvaluator());
+ evaluators.put(RelationalOperator.LTEALL, new LessThanEqualsAllEvaluator());
+ evaluators.put(RelationalOperator.LTANY, new LessThanAnyEvaluator());
+ evaluators.put(RelationalOperator.LTEANY, new LessThanEqualsAnyEvaluator());
+ evaluators.put(RelationalOperator.DATEEQ, new DateMatchEvaluator());
+ evaluators.put(RelationalOperator.DAYEQ, new DayMatchEvaluator());
+ evaluators.put(RelationalOperator.DAYIN, new DayInEvaluator());
+ evaluators.put(RelationalOperator.MONTHEQ, new MonthMatchEvaluator());
+ evaluators.put(RelationalOperator.MONTHIN, new MonthInEvaluator());
+ evaluators.put(RelationalOperator.YEAREQ, new YearMatchEvaluator());
+ evaluators.put(RelationalOperator.YEARIN, new YearInEvaluator());
+ evaluators.put(RelationalOperator.BEFORE, new BeforeEvaluator());
+ evaluators.put(RelationalOperator.AFTER, new AfterEvaluator());
+ evaluators.put(RelationalOperator.HOUREQ, new HourMatchEvaluator());
+ evaluators.put(RelationalOperator.HOURIN, new HourInEvaluator());
+ evaluators.put(RelationalOperator.TIMEBEFORE, new TimeBeforeEvaluator());
+ evaluators.put(RelationalOperator.TIMEAFTER, new TimeAfterEvaluator());
+ evaluators.put(RelationalOperator.NOTCONTAINS, new NotContainsEvaluator());
+ evaluators.put(RelationalOperator.ALLMATCH, new AllMatchEvaluator());
+ evaluators.put(RelationalOperator.ANYMATCH, new AnyMatchEvaluator());
+ evaluators.put(RelationalOperator.NONEMATCH, new NoneMatchEvaluator());
+ evaluators.put(RelationalOperator.EXACTMATCH, new ExactMatchEvaluator());
+ evaluators.put(RelationalOperator.WINDOWIN, new WindowInEvaluator());
+ evaluators.put(RelationalOperator.WINDOWOUT, new WindowOutEvaluator());
+ evaluators.put(RelationalOperator.WINDOWTIMEIN, new WindowTimeInEvaluator());
+ evaluators.put(RelationalOperator.WINDOWTIMEOUT, new WindowTimeOutEvaluator());
}
- public static Evaluator createEvaluator(RelationalOperator operator){
+ public static Evaluator createEvaluator(RelationalOperator operator) {
return evaluators.get(operator);
}
private static class ExistsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
- if(!left.isBooleanNode() && !right.isBooleanNode()){
+ if (!left.isBooleanNode() && !right.isBooleanNode()) {
throw new JsonPathException("Failed to evaluate exists expression");
}
return left.asBooleanNode().getBoolean() == right.asBooleanNode().getBoolean();
@@ -68,7 +106,7 @@ public class EvaluatorFactory {
private static class EqualsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
- if(left.isJsonNode() && right.isJsonNode()){
+ if (left.isJsonNode() && right.isJsonNode()) {
return left.asJsonNode().equals(right.asJsonNode(), ctx);
} else {
return left.equals(right);
@@ -79,7 +117,7 @@ public class EvaluatorFactory {
private static class TypeSafeEqualsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
- if(!left.getClass().equals(right.getClass())){
+ if (!left.getClass().equals(right.getClass())) {
return false;
}
return evaluators.get(RelationalOperator.EQ).evaluate(left, right, ctx);
@@ -96,70 +134,378 @@ public class EvaluatorFactory {
private static class LessThanEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
- if(left.isNumberNode() && right.isNumberNode()){
+ if (left.isNumberNode() && right.isNumberNode()) {
return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) < 0;
- } if(left.isStringNode() && right.isStringNode()){
+ }
+ if (left.isStringNode() && right.isStringNode()) {
return left.asStringNode().getString().compareTo(right.asStringNode().getString()) < 0;
- } if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()){ //workaround for issue: https://github.com/json-path/JsonPath/issues/613
+ }
+ if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()) { //workaround for issue: https://github.com/json-path/JsonPath/issues/613
return left.asOffsetDateTimeNode().getDate().compareTo(right.asOffsetDateTimeNode().getDate()) < 0;
}
return false;
}
}
+ private static class LessThanAllEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ValueListNode leftListNode = left.isValueListNode() ? left.asValueListNode() : null;
+ ValueListNode rightListNode = right.isValueListNode() ? right.asValueListNode() : null;
+ if (leftListNode == null) {
+ leftListNode = convertJsonNodeToListNode(left, ctx);
+ }
+ if (rightListNode == null) {
+ rightListNode = convertJsonNodeToListNode(right, ctx);
+ }
+ if (leftListNode == null || rightListNode == null) {
+ return false;
+ }
+ if (leftListNode.getNodes().get(0).isNumberNode() && rightListNode.getNodes().get(0).isNumberNode()) {
+ BigDecimal smallest = leftListNode.getNodes().stream().map(node ->
+ node.asNumberNode().getNumber()).min(Comparator.naturalOrder()).get();
+ return rightListNode.getNodes().stream().allMatch(node -> node.asNumberNode()
+ .getNumber().compareTo(smallest) < 0);
+ }
+ return false;
+ }
+
+ private ValueListNode convertJsonNodeToListNode(ValueNode node, Predicate.PredicateContext ctx) {
+ ValueListNode valueListNode = null;
+ ValueNode vn = node.isNumberNode() || node.isStringNode() ?
+ new ValueListNode(Collections.singleton(node.asNumberNode())) :
+ node.asJsonNode().asValueListNode(ctx);
+ if (!vn.isUndefinedNode()) {
+ valueListNode = vn.asValueListNode();
+ }
+ return valueListNode;
+ }
+ }
+
+ private static class LessThanAnyEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ValueListNode leftListNode = left.isValueListNode() ? left.asValueListNode() : null;
+ ValueListNode rightListNode = right.isValueListNode() ? right.asValueListNode() : null;
+ if (leftListNode == null) {
+ leftListNode = convertJsonNodeToListNode(left, ctx);
+ }
+ if (rightListNode == null) {
+ rightListNode = convertJsonNodeToListNode(right, ctx);
+ }
+ if (leftListNode == null || rightListNode == null) {
+ return false;
+ }
+ if (leftListNode.getNodes().get(0).isNumberNode() && rightListNode.getNodes().get(0).isNumberNode()) {
+ boolean res = false;
+ for (ValueNode field : leftListNode.getNodes()) {
+ for (ValueNode value : rightListNode.getNodes()) {
+ if (field.asNumberNode().getNumber().compareTo(value.asNumberNode().getNumber()) < 0) {
+ res = true;
+ break;
+ }
+ }
+ }
+ return res;
+ }
+ return false;
+ }
+
+ private ValueListNode convertJsonNodeToListNode(ValueNode node, Predicate.PredicateContext ctx) {
+ ValueListNode valueListNode = null;
+ ValueNode vn = node.isNumberNode() || node.isStringNode() ?
+ new ValueListNode(Collections.singleton(node.asNumberNode())) :
+ node.asJsonNode().asValueListNode(ctx);
+ if (!vn.isUndefinedNode()) {
+ valueListNode = vn.asValueListNode();
+ }
+ return valueListNode;
+ }
+ }
+
private static class LessThanEqualsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
- if(left.isNumberNode() && right.isNumberNode()){
+ if (left.isNumberNode() && right.isNumberNode()) {
return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) <= 0;
- } if(left.isStringNode() && right.isStringNode()){
+ }
+ if (left.isStringNode() && right.isStringNode()) {
return left.asStringNode().getString().compareTo(right.asStringNode().getString()) <= 0;
- } if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()){ //workaround for issue: https://github.com/json-path/JsonPath/issues/613
+ }
+ if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()) { //workaround for issue: https://github.com/json-path/JsonPath/issues/613
return left.asOffsetDateTimeNode().getDate().compareTo(right.asOffsetDateTimeNode().getDate()) <= 0;
}
return false;
}
}
+ private static class LessThanEqualsAllEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ValueListNode leftListNode = left.isValueListNode() ? left.asValueListNode() : null;
+ ValueListNode rightListNode = right.isValueListNode() ? right.asValueListNode() : null;
+ if (leftListNode == null) {
+ leftListNode = convertJsonNodeToListNode(left, ctx);
+ }
+ if (rightListNode == null) {
+ rightListNode = convertJsonNodeToListNode(right, ctx);
+ }
+ if (leftListNode == null || rightListNode == null) {
+ return false;
+ }
+ if (leftListNode.getNodes().get(0).isNumberNode() && rightListNode.getNodes().get(0).isNumberNode()) {
+ BigDecimal smallest = leftListNode.getNodes().stream().map(node ->
+ node.asNumberNode().getNumber()).min(Comparator.naturalOrder()).get();
+ return rightListNode.getNodes().stream().allMatch(node -> node.asNumberNode()
+ .getNumber().compareTo(smallest) <= 0);
+ }
+ return false;
+ }
+
+ private ValueListNode convertJsonNodeToListNode(ValueNode node, Predicate.PredicateContext ctx) {
+ ValueListNode valueListNode = null;
+ ValueNode vn = node.isNumberNode() || node.isStringNode() ?
+ new ValueListNode(Collections.singleton(node.asNumberNode())) :
+ node.asJsonNode().asValueListNode(ctx);
+ if (!vn.isUndefinedNode()) {
+ valueListNode = vn.asValueListNode();
+ }
+ return valueListNode;
+ }
+ }
+
+ private static class LessThanEqualsAnyEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ValueListNode leftListNode = left.isValueListNode() ? left.asValueListNode() : null;
+ ValueListNode rightListNode = right.isValueListNode() ? right.asValueListNode() : null;
+ if (leftListNode == null) {
+ leftListNode = convertJsonNodeToListNode(left, ctx);
+ }
+ if (rightListNode == null) {
+ rightListNode = convertJsonNodeToListNode(right, ctx);
+ }
+ if (leftListNode == null || rightListNode == null) {
+ return false;
+ }
+ if (leftListNode.getNodes().get(0).isNumberNode() && rightListNode.getNodes().get(0).isNumberNode()) {
+ boolean res = false;
+ for (ValueNode field : leftListNode.getNodes()) {
+ for (ValueNode value : rightListNode.getNodes()) {
+ if (field.asNumberNode().getNumber().compareTo(value.asNumberNode().getNumber()) <= 0) {
+ res = true;
+ break;
+ }
+ }
+ }
+ return res;
+ }
+ return false;
+ }
+
+ private ValueListNode convertJsonNodeToListNode(ValueNode node, Predicate.PredicateContext ctx) {
+ ValueListNode valueListNode = null;
+ ValueNode vn = node.isNumberNode() || node.isStringNode() ?
+ new ValueListNode(Collections.singleton(node.asNumberNode())) :
+ node.asJsonNode().asValueListNode(ctx);
+ if (!vn.isUndefinedNode()) {
+ valueListNode = vn.asValueListNode();
+ }
+ return valueListNode;
+ }
+ }
+
private static class GreaterThanEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
- if(left.isNumberNode() && right.isNumberNode()){
+ if (left.isNumberNode() && right.isNumberNode()) {
return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) > 0;
- } else if(left.isStringNode() && right.isStringNode()){
+ } else if (left.isStringNode() && right.isStringNode()) {
return left.asStringNode().getString().compareTo(right.asStringNode().getString()) > 0;
- } else if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()){ //workaround for issue: https://github.com/json-path/JsonPath/issues/613
+ } else if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()) { //workaround for issue: https://github.com/json-path/JsonPath/issues/613
return left.asOffsetDateTimeNode().getDate().compareTo(right.asOffsetDateTimeNode().getDate()) > 0;
}
return false;
}
}
+ private static class GreaterThanAllEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ValueListNode leftListNode = left.isValueListNode() ? left.asValueListNode() : null;
+ ValueListNode rightListNode = right.isValueListNode() ? right.asValueListNode() : null;
+ if (leftListNode == null) {
+ leftListNode = convertJsonNodeToListNode(left, ctx);
+ }
+ if (rightListNode == null) {
+ rightListNode = convertJsonNodeToListNode(right, ctx);
+ }
+ if (leftListNode == null || rightListNode == null) {
+ return false;
+ }
+ if (leftListNode.getNodes().get(0).isNumberNode() && rightListNode.getNodes().get(0).isNumberNode()) {
+ BigDecimal largest = leftListNode.getNodes().stream().map(node ->
+ node.asNumberNode().getNumber()).max(Comparator.naturalOrder()).get();
+ return rightListNode.getNodes().stream().allMatch(node -> node.asNumberNode()
+ .getNumber().compareTo(largest) < 0);
+ }
+ return false;
+ }
+
+ private ValueListNode convertJsonNodeToListNode(ValueNode node, Predicate.PredicateContext ctx) {
+ ValueListNode valueListNode = null;
+ ValueNode vn = node.isNumberNode() || node.isStringNode() ?
+ new ValueListNode(Collections.singleton(node.asNumberNode())) :
+ node.asJsonNode().asValueListNode(ctx);
+ if (!vn.isUndefinedNode()) {
+ valueListNode = vn.asValueListNode();
+ }
+ return valueListNode;
+ }
+ }
+
+ private static class GreaterThanAnyEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ValueListNode leftListNode = left.isValueListNode() ? left.asValueListNode() : null;
+ ValueListNode rightListNode = right.isValueListNode() ? right.asValueListNode() : null;
+ if (leftListNode == null) {
+ leftListNode = convertJsonNodeToListNode(left, ctx);
+ }
+ if (rightListNode == null) {
+ rightListNode = convertJsonNodeToListNode(right, ctx);
+ }
+ if (leftListNode == null || rightListNode == null) {
+ return false;
+ }
+ if (leftListNode.getNodes().get(0).isNumberNode() && rightListNode.getNodes().get(0).isNumberNode()) {
+ boolean res = false;
+ for (ValueNode field : leftListNode.getNodes()) {
+ for (ValueNode value : rightListNode.getNodes()) {
+ if (field.asNumberNode().getNumber().compareTo(value.asNumberNode().getNumber()) > 0) {
+ res = true;
+ break;
+ }
+ }
+ }
+ return res;
+ }
+ return false;
+ }
+
+ private ValueListNode convertJsonNodeToListNode(ValueNode node, Predicate.PredicateContext ctx) {
+ ValueListNode valueListNode = null;
+ ValueNode vn = node.isNumberNode() || node.isStringNode() ?
+ new ValueListNode(Collections.singleton(node.asNumberNode())) :
+ node.asJsonNode().asValueListNode(ctx);
+ if (!vn.isUndefinedNode()) {
+ valueListNode = vn.asValueListNode();
+ }
+ return valueListNode;
+ }
+ }
+
private static class GreaterThanEqualsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
- if(left.isNumberNode() && right.isNumberNode()){
+ if (left.isNumberNode() && right.isNumberNode()) {
return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) >= 0;
- } else if(left.isStringNode() && right.isStringNode()){
+ } else if (left.isStringNode() && right.isStringNode()) {
return left.asStringNode().getString().compareTo(right.asStringNode().getString()) >= 0;
- } else if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()){ //workaround for issue: https://github.com/json-path/JsonPath/issues/613
+ } else if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()) { //workaround for issue: https://github.com/json-path/JsonPath/issues/613
return left.asOffsetDateTimeNode().getDate().compareTo(right.asOffsetDateTimeNode().getDate()) >= 0;
}
return false;
}
}
+ private static class GreaterThanEqualsAllEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ValueListNode leftListNode = left.isValueListNode() ? left.asValueListNode() : null;
+ ValueListNode rightListNode = right.isValueListNode() ? right.asValueListNode() : null;
+ if (leftListNode == null) {
+ leftListNode = convertJsonNodeToListNode(left, ctx);
+ }
+ if (rightListNode == null) {
+ rightListNode = convertJsonNodeToListNode(right, ctx);
+ }
+ if (leftListNode == null || rightListNode == null) {
+ return false;
+ }
+ if (leftListNode.getNodes().get(0).isNumberNode() && rightListNode.getNodes().get(0).isNumberNode()) {
+ BigDecimal largest = leftListNode.getNodes().stream().map(node ->
+ node.asNumberNode().getNumber()).max(Comparator.naturalOrder()).get();
+ return rightListNode.getNodes().stream().allMatch(node -> node.asNumberNode()
+ .getNumber().compareTo(largest) <= 0);
+ }
+ return false;
+ }
+
+ private ValueListNode convertJsonNodeToListNode(ValueNode node, Predicate.PredicateContext ctx) {
+ ValueListNode valueListNode = null;
+ ValueNode vn = node.isNumberNode() || node.isStringNode() ?
+ new ValueListNode(Collections.singleton(node.asNumberNode())) :
+ node.asJsonNode().asValueListNode(ctx);
+ if (!vn.isUndefinedNode()) {
+ valueListNode = vn.asValueListNode();
+ }
+ return valueListNode;
+ }
+ }
+
+ private static class GreaterThanEqualsAnyEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ValueListNode leftListNode = left.isValueListNode() ? left.asValueListNode() : null;
+ ValueListNode rightListNode = right.isValueListNode() ? right.asValueListNode() : null;
+ if (leftListNode == null) {
+ leftListNode = convertJsonNodeToListNode(left, ctx);
+ }
+ if (rightListNode == null) {
+ rightListNode = convertJsonNodeToListNode(right, ctx);
+ }
+ if (leftListNode == null || rightListNode == null) {
+ return false;
+ }
+ if (leftListNode.getNodes().get(0).isNumberNode() && rightListNode.getNodes().get(0).isNumberNode()) {
+ boolean res = false;
+ for (ValueNode field : leftListNode.getNodes()) {
+ for (ValueNode value : rightListNode.getNodes()) {
+ if (field.asNumberNode().getNumber().compareTo(value.asNumberNode().getNumber()) >= 0) {
+ res = true;
+ break;
+ }
+ }
+ }
+ return res;
+ }
+ return false;
+ }
+
+ private ValueListNode convertJsonNodeToListNode(ValueNode node, Predicate.PredicateContext ctx) {
+ ValueListNode valueListNode = null;
+ ValueNode vn = node.isNumberNode() || node.isStringNode() ?
+ new ValueListNode(Collections.singleton(node.asNumberNode())) :
+ node.asJsonNode().asValueListNode(ctx);
+ if (!vn.isUndefinedNode()) {
+ valueListNode = vn.asValueListNode();
+ }
+ return valueListNode;
+ }
+ }
+
private static class SizeEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
- if (! right.isNumberNode()) {
+ if (!right.isNumberNode()) {
return false;
}
int expectedSize = right.asNumberNode().getNumber().intValue();
- if(left.isStringNode()){
+ if (left.isStringNode()) {
return left.asStringNode().length() == expectedSize;
- } else if(left.isJsonNode()){
+ } else if (left.isJsonNode()) {
return left.asJsonNode().length(ctx) == expectedSize;
}
return false;
@@ -169,9 +515,9 @@ public class EvaluatorFactory {
private static class EmptyEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
- if(left.isStringNode()){
+ if (left.isStringNode()) {
return left.asStringNode().isEmpty() == right.asBooleanNode().getBoolean();
- } else if(left.isJsonNode()){
+ } else if (left.isJsonNode()) {
return left.asJsonNode().isEmpty(ctx) == right.asBooleanNode().getBoolean();
}
return false;
@@ -182,9 +528,9 @@ public class EvaluatorFactory {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
ValueListNode valueListNode;
- if(right.isJsonNode()){
+ if (right.isJsonNode()) {
ValueNode vn = right.asJsonNode().asValueListNode(ctx);
- if(vn.isUndefinedNode()){
+ if (vn.isUndefinedNode()) {
return false;
} else {
valueListNode = vn.asValueListNode();
@@ -208,12 +554,12 @@ public class EvaluatorFactory {
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
ValueListNode requiredValues = right.asValueListNode();
- if(left.isJsonNode()){
+ if (left.isJsonNode()) {
ValueNode valueNode = left.asJsonNode().asValueListNode(ctx); //returns UndefinedNode if conversion is not possible
- if(valueNode.isValueListNode()){
+ if (valueNode.isValueListNode()) {
ValueListNode shouldContainAll = valueNode.asValueListNode();
for (ValueNode required : requiredValues) {
- if(!shouldContainAll.contains(required)){
+ if (!shouldContainAll.contains(required)) {
return false;
}
}
@@ -227,14 +573,29 @@ public class EvaluatorFactory {
private static class ContainsEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
- if(left.isStringNode() && right.isStringNode()){
+ if (left.isStringNode() && right.isStringNode()) {
return left.asStringNode().contains(right.asStringNode().getString());
- } else if(left.isJsonNode()){
+ } else if (left.isJsonNode()) {
+ ValueNode valueNode = left.asJsonNode().asValueListNode(ctx);
+ if (valueNode.isUndefinedNode()) return false;
+ else {
+ return valueNode.asValueListNode().contains(right);
+ }
+ }
+ return false;
+ }
+ }
+
+ private static class NotContainsEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ if (left.isStringNode() && right.isStringNode()) {
+ return !(left.asStringNode().contains(right.asStringNode().getString()));
+ } else if (left.isJsonNode()) {
ValueNode valueNode = left.asJsonNode().asValueListNode(ctx);
- if(valueNode.isUndefinedNode()) return false;
+ if (valueNode.isUndefinedNode()) return false;
else {
- boolean res = valueNode.asValueListNode().contains(right);
- return res;
+ return !(valueNode.asValueListNode().contains(right));
}
}
return false;
@@ -251,7 +612,7 @@ public class EvaluatorFactory {
private static class RegexpEvaluator implements Evaluator {
@Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
- if(!(left.isPatternNode() ^ right.isPatternNode())){
+ if (!(left.isPatternNode() ^ right.isPatternNode())) {
return false;
}
@@ -280,33 +641,33 @@ public class EvaluatorFactory {
}
private static class SubsetOfEvaluator implements Evaluator {
- @Override
- public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
- ValueListNode rightValueListNode;
- if(right.isJsonNode()){
- ValueNode vn = right.asJsonNode().asValueListNode(ctx);
- if(vn.isUndefinedNode()){
- return false;
- } else {
- rightValueListNode = vn.asValueListNode();
- }
- } else {
- rightValueListNode = right.asValueListNode();
- }
- ValueListNode leftValueListNode;
- if(left.isJsonNode()){
- ValueNode vn = left.asJsonNode().asValueListNode(ctx);
- if(vn.isUndefinedNode()){
- return false;
- } else {
- leftValueListNode = vn.asValueListNode();
- }
- } else {
- leftValueListNode = left.asValueListNode();
- }
- return leftValueListNode.subsetof(rightValueListNode);
- }
- }
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ValueListNode rightValueListNode;
+ if (right.isJsonNode()) {
+ ValueNode vn = right.asJsonNode().asValueListNode(ctx);
+ if (vn.isUndefinedNode()) {
+ return false;
+ } else {
+ rightValueListNode = vn.asValueListNode();
+ }
+ } else {
+ rightValueListNode = right.asValueListNode();
+ }
+ ValueListNode leftValueListNode;
+ if (left.isJsonNode()) {
+ ValueNode vn = left.asJsonNode().asValueListNode(ctx);
+ if (vn.isUndefinedNode()) {
+ return false;
+ } else {
+ leftValueListNode = vn.asValueListNode();
+ }
+ } else {
+ leftValueListNode = left.asValueListNode();
+ }
+ return leftValueListNode.subsetof(rightValueListNode);
+ }
+ }
private static class AnyOfEvaluator implements Evaluator {
@Override
@@ -381,4 +742,354 @@ public class EvaluatorFactory {
return true;
}
}
+
+ private static class DateMatchEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ZonedDateTime compDate = left.asDateNode().getDate();
+ ZonedDateTime evalDate = right.asDateNode().getDate().withZoneSameLocal(compDate.getZone());
+ return compDate.toLocalDate().compareTo(evalDate.toLocalDate()) == 0;
+ }
+ }
+
+ private static class MonthMatchEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ try {
+ ZonedDateTime compDate = left.asDateNode().getDate();
+ ZonedDateTime evalDate = right.asDateNode().getDate().withZoneSameLocal(compDate.getZone());
+ return compDate.getMonth().compareTo(evalDate.getMonth()) == 0;
+ } catch (InvalidPathException e) {
+ Month month;
+ if (right.isStringNode()) {
+ month = Month.valueOf(right.asStringNode().getString());
+ } else {
+ month = Month.of(right.asNumberNode().getNumber().intValue());
+ }
+ return left.asDateNode().getDate().getMonth() == month;
+ }
+ }
+ }
+
+ private static class MonthInEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ValueNodes.DateNode leftListNode = left.isDateNode() ? left.asDateNode() : null;
+ ValueListNode rightListNode = right.isValueListNode() ? right.asValueListNode() : null;
+ if (rightListNode == null) {
+ rightListNode = convertJsonNodeToListNode(right, ctx);
+ }
+ if (leftListNode == null || rightListNode == null) {
+ return false;
+ }
+ ZonedDateTime compDate = leftListNode.getDate();
+ int month = compDate.getMonthValue();
+ if (rightListNode.getNodes().get(0).isDateNode()) {
+ return rightListNode.getNodes().stream().anyMatch(node ->
+ node.asDateNode().getDate().withZoneSameLocal(compDate.getZone()).getMonthValue() == month);
+ } else if (rightListNode.getNodes().get(0).isStringNode()) {
+ return rightListNode.getNodes().stream().anyMatch(node ->
+ Month.valueOf(node.asStringNode().getString()).getValue() == month);
+ } else if (rightListNode.getNodes().get(0).isNumberNode()) {
+ return rightListNode.getNodes().stream().anyMatch(node ->
+ Month.of(node.asNumberNode().getNumber().intValue()).getValue() == month);
+ }
+ return false;
+ }
+
+ private ValueListNode convertJsonNodeToListNode(ValueNode node, Predicate.PredicateContext ctx) {
+ ValueListNode valueListNode = null;
+ ValueNode vn;
+ try {
+ vn = new ValueListNode(Collections.singleton(node.asDateNode()));
+ } catch (InvalidPathException e) {
+ if (node.isStringNode()) {
+ vn = new ValueListNode(Collections.singleton(node.asStringNode()));
+ } else if (node.isJsonNode()) {
+ vn = node.asJsonNode().asValueListNode(ctx);
+ } else {
+ vn = new ValueListNode(Collections.singleton(node.asNumberNode()));
+ }
+ }
+ if (!vn.isUndefinedNode()) {
+ valueListNode = vn.asValueListNode();
+ }
+ return valueListNode;
+ }
+ }
+
+ private static class DayMatchEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ try {
+ ZonedDateTime compDate = left.asDateNode().getDate();
+ ZonedDateTime evalDate = right.asDateNode().getDate().withZoneSameLocal(compDate.getZone());
+ return compDate.getDayOfMonth() == evalDate.getDayOfMonth();
+ } catch (InvalidPathException e) {
+ return left.asDateNode().getDate().getDayOfMonth() == right.asNumberNode().getNumber().intValue();
+ }
+ }
+ }
+
+ private static class DayInEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ValueNodes.DateNode leftListNode = left.isDateNode() ? left.asDateNode() : null;
+ ValueListNode rightListNode = right.isValueListNode() ? right.asValueListNode() : null;
+ if (rightListNode == null) {
+ rightListNode = convertJsonNodeToListNode(right, ctx);
+ }
+ if (leftListNode == null || rightListNode == null) {
+ return false;
+ }
+ ZonedDateTime compDate = leftListNode.getDate();
+ int day = compDate.getDayOfMonth();
+ if (rightListNode.getNodes().get(0).isDateNode()) {
+ return rightListNode.getNodes().stream().anyMatch(node ->
+ node.asDateNode().getDate().withZoneSameLocal(compDate.getZone()).getDayOfMonth() == day);
+ }
+ return rightListNode.getNodes().stream()
+ .anyMatch(node -> node.asNumberNode().getNumber().intValue() == day);
+ }
+
+ private ValueListNode convertJsonNodeToListNode(ValueNode node, Predicate.PredicateContext ctx) {
+ ValueListNode valueListNode = null;
+ ValueNode vn;
+ try {
+ vn = new ValueListNode(Collections.singleton(node.asDateNode()));
+ } catch (InvalidPathException e) {
+ if (node.isStringNode()) {
+ vn = new ValueListNode(Collections.singleton(node.asStringNode()));
+ } else if (node.isJsonNode()) {
+ vn = node.asJsonNode().asValueListNode(ctx);
+ } else {
+ vn = new ValueListNode(Collections.singleton(node.asNumberNode()));
+ }
+ }
+ if (!vn.isUndefinedNode()) {
+ valueListNode = vn.asValueListNode();
+ }
+ return valueListNode;
+ }
+ }
+
+ private static class YearMatchEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ try {
+ ZonedDateTime compDate = left.asDateNode().getDate();
+ ZonedDateTime evalDate = right.asDateNode().getDate().withZoneSameLocal(compDate.getZone());
+ return compDate.getYear() == evalDate.getYear();
+ } catch (InvalidPathException e) {
+ return left.asDateNode().getDate().getYear() == right.asNumberNode().getNumber().intValue();
+ }
+ }
+ }
+
+ private static class YearInEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ValueNodes.DateNode leftListNode = left.isDateNode() ? left.asDateNode() : null;
+ ValueListNode rightListNode = right.isValueListNode() ? right.asValueListNode() : null;
+ if (rightListNode == null) {
+ rightListNode = convertJsonNodeToListNode(right, ctx);
+ }
+ if (leftListNode == null || rightListNode == null) {
+ return false;
+ }
+ ZonedDateTime compDate = leftListNode.getDate();
+ int year = compDate.getYear();
+ if (rightListNode.getNodes().get(0).isDateNode()) {
+ return rightListNode.getNodes().stream().anyMatch(node ->
+ node.asDateNode().getDate().withZoneSameLocal(compDate.getZone()).getYear() == year);
+ }
+ return rightListNode.getNodes().stream()
+ .anyMatch(node -> node.asNumberNode().getNumber().intValue() == year);
+ }
+
+ private ValueListNode convertJsonNodeToListNode(ValueNode node, Predicate.PredicateContext ctx) {
+ ValueListNode valueListNode = null;
+ ValueNode vn;
+ try {
+ vn = new ValueListNode(Collections.singleton(node.asDateNode()));
+ } catch (InvalidPathException e) {
+ if (node.isStringNode()) {
+ vn = new ValueListNode(Collections.singleton(node.asStringNode()));
+ } else if (node.isJsonNode()) {
+ vn = node.asJsonNode().asValueListNode(ctx);
+ } else {
+ vn = new ValueListNode(Collections.singleton(node.asNumberNode()));
+ }
+ }
+ if (!vn.isUndefinedNode()) {
+ valueListNode = vn.asValueListNode();
+ }
+ return valueListNode;
+ }
+ }
+
+ private static class BeforeEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ZonedDateTime compDate = left.asDateNode().getDate();
+ ZonedDateTime evalDate = right.asDateNode().getDate().withZoneSameLocal(compDate.getZone());
+ return compDate.isBefore(evalDate);
+ }
+ }
+
+ private static class AfterEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ZonedDateTime compDate = left.asDateNode().getDate();
+ ZonedDateTime evalDate = right.asDateNode().getDate().withZoneSameLocal(compDate.getZone());
+ return compDate.isAfter(evalDate);
+ }
+ }
+
+ private static class HourMatchEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ try {
+ ZonedDateTime compDate = left.asDateNode().getDate();
+ ZonedDateTime evalDate = right.asDateNode().getDate().withZoneSameLocal(compDate.getZone());
+ return compDate.getHour() == evalDate.getHour();
+ } catch (InvalidPathException e) {
+ return left.asDateNode().getDate().getHour() == right.asNumberNode().getNumber().intValue();
+ }
+ }
+ }
+
+ private static class HourInEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ValueNodes.DateNode leftListNode = left.isDateNode() ? left.asDateNode() : null;
+ ValueListNode rightListNode = right.isValueListNode() ? right.asValueListNode() : null;
+ if (rightListNode == null) {
+ rightListNode = convertJsonNodeToListNode(right, ctx);
+ }
+ if (leftListNode == null || rightListNode == null) {
+ return false;
+ }
+ ZonedDateTime compDate = leftListNode.getDate();
+ int hour = compDate.getHour();
+ if (rightListNode.getNodes().get(0).isDateNode()) {
+ return rightListNode.getNodes().stream().anyMatch(node ->
+ node.asDateNode().getDate().withZoneSameLocal(compDate.getZone()).getHour() == hour);
+ }
+ return rightListNode.getNodes().stream()
+ .anyMatch(node -> node.asNumberNode().getNumber().intValue() == hour);
+ }
+
+ private ValueListNode convertJsonNodeToListNode(ValueNode node, Predicate.PredicateContext ctx) {
+ ValueListNode valueListNode = null;
+ ValueNode vn;
+ try {
+ vn = new ValueListNode(Collections.singleton(node.asDateNode()));
+ } catch (InvalidPathException e) {
+ if (node.isStringNode()) {
+ vn = new ValueListNode(Collections.singleton(node.asStringNode()));
+ } else if (node.isJsonNode()) {
+ vn = node.asJsonNode().asValueListNode(ctx);
+ } else {
+ vn = new ValueListNode(Collections.singleton(node.asNumberNode()));
+ }
+ }
+ if (!vn.isUndefinedNode()) {
+ valueListNode = vn.asValueListNode();
+ }
+ return valueListNode;
+ }
+ }
+
+ private static class TimeBeforeEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ZonedDateTime date = left.asDateNode().getDate();
+ String[] time = right.asStringNode().getString().split(":");
+ ZonedDateTime evalDate = date.with(LocalTime.of(Integer.parseInt(time[0]), Integer.parseInt(time[1])));
+ return date.isBefore(evalDate);
+ }
+ }
+
+ private static class TimeAfterEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ZonedDateTime date = left.asDateNode().getDate();
+ String[] time = right.asStringNode().getString().split(":");
+ ZonedDateTime evalDate = date.with(LocalTime.of(Integer.parseInt(time[0]), Integer.parseInt(time[1])));
+ return date.isAfter(evalDate);
+ }
+ }
+
+ private static class AllMatchEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ return evaluators.get(RelationalOperator.SUBSETOF).evaluate(right, left, ctx);
+ }
+ }
+
+ private static class AnyMatchEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ return evaluators.get(RelationalOperator.ANYOF).evaluate(right, left, ctx);
+ }
+ }
+
+ private static class NoneMatchEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ return evaluators.get(RelationalOperator.NONEOF).evaluate(right, left, ctx);
+ }
+ }
+
+ private static class ExactMatchEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ return evaluators.get(RelationalOperator.ALL).evaluate(right, left, ctx);
+ }
+ }
+
+ private static class WindowInEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ZonedDateTime date = left.asDateNode().getDate();
+ ZonedDateTime now = ZonedDateTime.now(date.getZone());
+ int window = right.asNumberNode().getNumber().intValue();
+ LocalDate finalDate = now.toLocalDate().minusDays(window);
+ return date.toLocalDate().isAfter(finalDate);
+ }
+ }
+
+ private static class WindowOutEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ZonedDateTime date = left.asDateNode().getDate();
+ ZonedDateTime now = ZonedDateTime.now(date.getZone());
+ int window = right.asNumberNode().getNumber().intValue();
+ LocalDate finalDate = date.toLocalDate().minusDays(window);
+ return finalDate.isAfter(now.toLocalDate());
+ }
+ }
+
+ private static class WindowTimeInEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ZonedDateTime date = left.asDateNode().getDate();
+ ZonedDateTime now = ZonedDateTime.now(date.getZone());
+ int window = right.asNumberNode().getNumber().intValue();
+ ZonedDateTime finalDate = now.minusDays(window);
+ return date.isAfter(finalDate);
+ }
+ }
+
+ private static class WindowTimeOutEvaluator implements Evaluator {
+ @Override
+ public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
+ ZonedDateTime date = left.asDateNode().getDate();
+ ZonedDateTime now = ZonedDateTime.now(date.getZone());
+ int window = right.asNumberNode().getNumber().intValue();
+ ZonedDateTime finalDate = date.minusDays(window);
+ return finalDate.isAfter(now);
+ }
+ }
}
diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/RelationalOperator.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/RelationalOperator.java
index 50986945..932162c1 100644
--- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/RelationalOperator.java
+++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/RelationalOperator.java
@@ -34,7 +34,37 @@ public enum RelationalOperator {
EMPTY("EMPTY"),
SUBSETOF("SUBSETOF"),
ANYOF("ANYOF"),
- NONEOF("NONEOF");
+ NONEOF("NONEOF"),
+ GTALL("GTALL"),
+ GTEALL("GTEALL"),
+ GTANY("GTANY"),
+ GTEANY("GTEANY"),
+ LTALL("LTALL"),
+ LTEALL("LTEALL"),
+ LTANY("LTANY"),
+ LTEANY("LTEANY"),
+ DATEEQ("DATEEQ"),
+ MONTHEQ("MONTHEQ"),
+ DAYEQ("DAYEQ"),
+ YEAREQ("YEAREQ"),
+ MONTHIN("MONTHIN"),
+ DAYIN("DAYIN"),
+ YEARIN("YEARIN"),
+ BEFORE("BEFORE"),
+ AFTER("AFTER"),
+ HOUREQ("HOUREQ"),
+ HOURIN("HOURIN"),
+ TIMEBEFORE("TIMEBEFORE"),
+ TIMEAFTER("TIMEAFTER"),
+ NOTCONTAINS("NOTCONTAINS"),
+ ALLMATCH("ALLMATCH"),
+ ANYMATCH("ANYMATCH"),
+ NONEMATCH("NONEMATCH"),
+ EXACTMATCH("EXACTMATCH"),
+ WINDOWIN("WINDOWIN"),
+ WINDOWOUT("WINDOWOUT"),
+ WINDOWTIMEIN("WINDOWTIMEIN"),
+ WINDOWTIMEOUT("WINDOWTIMEOUT");
private final String operatorString;
diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java
index cdf0dd97..e4da1bde 100644
--- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java
+++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java
@@ -8,6 +8,8 @@ import com.jayway.jsonpath.internal.path.PathCompiler;
import net.minidev.json.parser.JSONParser;
import java.time.OffsetDateTime;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
import java.util.regex.Pattern;
import static com.jayway.jsonpath.internal.filter.ValueNodes.*;
@@ -113,6 +115,13 @@ public abstract class ValueNode {
throw new InvalidPathException("Expected offsetDateTime node");
}
+ public boolean isDateNode(){
+ return false;
+ }
+
+ public DateNode asDateNode(){
+ throw new InvalidPathException("Expected date node");
+ }
private static boolean isPath(Object o) {
if(o == null || !(o instanceof String)){
@@ -163,7 +172,7 @@ public abstract class ValueNode {
//
//----------------------------------------------------
public static ValueNode toValueNode(Object o){
-
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MMM yyyy HH:mm:ss VV");
if(o == null) return NULL_NODE;
if(o instanceof ValueNode) return (ValueNode)o;
if(o instanceof Class) return createClassNode((Class)o);
@@ -175,6 +184,7 @@ public abstract class ValueNode {
else if(o instanceof Boolean) return createBooleanNode(o.toString());
else if(o instanceof Pattern) return createPatternNode((Pattern)o);
else if (o instanceof OffsetDateTime) return createOffsetDateTimeNode(o.toString()); //workaround for issue: https://github.com/json-path/JsonPath/issues/613
+ else if (o instanceof ZonedDateTime) return createDateNode(((ZonedDateTime) o).format(formatter));
else throw new JsonPathException("Could not determine value type");
}
@@ -220,6 +230,9 @@ public abstract class ValueNode {
return new OffsetDateTimeNode(charSequence);
}
+ public static DateNode createDateNode(String date) {
+ return new DateNode(date);
+ }
public static UndefinedNode createUndefinedNode() {
return UNDEFINED;
diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java
index 3f459a8c..404ebedf 100644
--- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java
+++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java
@@ -2,14 +2,12 @@ package com.jayway.jsonpath.internal.filter;
import java.math.BigDecimal;
import java.time.OffsetDateTime;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Pattern;
-import com.jayway.jsonpath.Configuration;
-import com.jayway.jsonpath.JsonPathException;
-import com.jayway.jsonpath.Option;
-import com.jayway.jsonpath.PathNotFoundException;
-import com.jayway.jsonpath.Predicate;
+import com.jayway.jsonpath.*;
import com.jayway.jsonpath.internal.Path;
import com.jayway.jsonpath.internal.Utils;
import com.jayway.jsonpath.internal.path.PathCompiler;
@@ -227,6 +225,17 @@ public interface ValueNodes {
return new NumberNode(number);
}
+ @Override
+ public DateNode asDateNode() {
+ DateNode node;
+ try {
+ node = new DateNode(string);
+ } catch (IllegalArgumentException e) {
+ throw new InvalidPathException("Expected Timestamp format: dd MMM yyyy HH:mm:ss VV");
+ }
+ return node;
+ }
+
public String getString() {
return string;
}
@@ -379,7 +388,54 @@ public interface ValueNodes {
}
}
+ class DateNode extends ValueNode {
+
+ private final ZonedDateTime dateTime;
+ private final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MMM yyyy HH:mm:ss VV");
+
+ DateNode(ZonedDateTime dateTime) {
+ this.dateTime = dateTime;
+ }
+
+ DateNode(String date) {
+ dateTime = ZonedDateTime.parse(date, formatter);
+ }
+
+ @Override
+ public StringNode asStringNode() {
+ return new StringNode(dateTime.format(formatter), false);
+ }
+
+ public ZonedDateTime getDate() {
+ return dateTime;
+ }
+
+ @Override
+ public Class> type(Predicate.PredicateContext ctx) {
+ return DateNode.class;
+ }
+
+ public boolean isDateNode() {
+ return true;
+ }
+
+ public DateNode asDateNode() {
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return dateTime.toString();
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof OffsetDateTimeNode) && !(o instanceof StringNode)) return false;
+ DateNode that = ((ValueNode) o).asDateNode();
+ return dateTime.compareTo(that.dateTime) == 0;
+ }
+ }
class BooleanNode extends ValueNode {
private final Boolean value;
diff --git a/json-path/src/test/java/com/jayway/jsonpath/FilterParseTest.java b/json-path/src/test/java/com/jayway/jsonpath/FilterParseTest.java
index 37e37f79..0980e154 100644
--- a/json-path/src/test/java/com/jayway/jsonpath/FilterParseTest.java
+++ b/json-path/src/test/java/com/jayway/jsonpath/FilterParseTest.java
@@ -91,6 +91,34 @@ public class FilterParseTest {
assertThat(filter).isEqualTo(parsed);
}
+ @Test
+ public void a_ltall_filter_can_be_serialized() {
+ String filter = filter(where("a").ltall(1)).toString();
+ String parsed = parse("[?(@['a'] LTALL [1])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_lteall_filter_can_be_serialized() {
+ String filter = filter(where("a").lteall(1)).toString();
+ String parsed = parse("[?(@['a'] LTEALL [1])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_ltany_filter_can_be_serialized() {
+ String filter = filter(where("a").ltany(1)).toString();
+ String parsed = parse("[?(@['a'] LTANY [1])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_lteany_filter_can_be_serialized() {
+ String filter = filter(where("a").lteany(1)).toString();
+ String parsed = parse("[?(@['a'] LTEANY [1])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
@Test
public void a_gt_filter_can_be_serialized() {
@@ -100,6 +128,34 @@ public class FilterParseTest {
assertThat(filter).isEqualTo(parsed);
}
+ @Test
+ public void a_gtall_filter_can_be_serialized() {
+ String filter = filter(where("a").gtall(1)).toString();
+ String parsed = parse("[?(@['a'] GTALL [1])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_gteall_filter_can_be_serialized() {
+ String filter = filter(where("a").gteall(1)).toString();
+ String parsed = parse("[?(@['a'] GTEALL [1])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_gtany_filter_can_be_serialized() {
+ String filter = filter(where("a").gtany(1)).toString();
+ String parsed = parse("[?(@['a'] GTANY [1])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_gteany_filter_can_be_serialized() {
+ String filter = filter(where("a").gteany(1)).toString();
+ String parsed = parse("[?(@['a'] GTEANY [1])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
@Test
public void a_nin_filter_can_be_serialized() {
String filter = filter(where("a").nin(1)).toString();
@@ -125,6 +181,13 @@ public class FilterParseTest {
assertThat(filter).isEqualTo(parsed);
}
+ @Test
+ public void a_notcontains_filter_can_be_serialized() {
+ String filter = filter(where("a").notcontains("a")).toString();
+ String parsed = parse("[?(@['a'] NOTCONTAINS 'a')]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
@Test
public void a_all_filter_can_be_serialized() {
@@ -152,6 +215,15 @@ public class FilterParseTest {
assertThat(filter).isEqualTo(parsed);
}
+ @Test
+ public void a_subsetof_objectrange_filter_can_be_serialized() {
+
+ String filter = filter(where("a").subsetof("a")).toString();
+ String parsed = parse("[?(@['a'] SUBSETOF ['a'])]").toString();
+
+ assertThat(filter).isEqualTo(parsed);
+ }
+
@Test
public void a_anyof_filter_can_be_serialized() {
@@ -161,6 +233,15 @@ public class FilterParseTest {
assertThat(filter).isEqualTo(parsed);
}
+ @Test
+ public void a_anyof_objectrange_filter_can_be_serialized() {
+
+ String filter = filter(where("a").anyof("a")).toString();
+ String parsed = parse("[?(@['a'] ANYOF ['a'])]").toString();
+
+ assertThat(filter).isEqualTo(parsed);
+ }
+
@Test
public void a_noneof_filter_can_be_serialized() {
@@ -170,6 +251,15 @@ public class FilterParseTest {
assertThat(filter).isEqualTo(parsed);
}
+ @Test
+ public void a_noneof_objectrange_filter_can_be_serialized() {
+
+ String filter = filter(where("a").noneof("a")).toString();
+ String parsed = parse("[?(@['a'] NONEOF ['a'])]").toString();
+
+ assertThat(filter).isEqualTo(parsed);
+ }
+
@Test
public void a_exists_filter_can_be_serialized() {
@@ -275,4 +365,179 @@ public class FilterParseTest {
assertThat(filter).isEqualTo(parsed);
}
+
+ @Test
+ public void a_allmatch_filter_can_be_serialized() {
+ String filter = filter(where("a").allmatch(Collections.emptyList())).toString();
+ String parsed = parse("[?(@['a'] ALLMATCH [])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_anymatch_filter_can_be_serialized() {
+ String filter = filter(where("a").anymatch(Collections.emptyList())).toString();
+ String parsed = parse("[?(@['a'] ANYMATCH [])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_nonematch_filter_can_be_serialized() {
+ String filter = filter(where("a").nonematch(Collections.emptyList())).toString();
+ String parsed = parse("[?(@['a'] NONEMATCH [])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_exactmatch_filter_can_be_serialized() {
+ String filter = filter(where("a").exactmatch(Collections.emptyList())).toString();
+ String parsed = parse("[?(@['a'] EXACTMATCH [])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_allmatch_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").allmatch("a")).toString();
+ String parsed = parse("[?(@['a'] ALLMATCH ['a'])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_anymatch_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").anymatch("a")).toString();
+ String parsed = parse("[?(@['a'] ANYMATCH ['a'])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_nonematch_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").nonematch("a")).toString();
+ String parsed = parse("[?(@['a'] NONEMATCH ['a'])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_exactmatch_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").exactmatch("a")).toString();
+ String parsed = parse("[?(@['a'] EXACTMATCH ['a'])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_dateeq_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").dateeq("a")).toString();
+ String parsed = parse("[?(@['a'] DATEEQ 'a')]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_dayeq_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").dayeq("a")).toString();
+ String parsed = parse("[?(@['a'] DAYEQ 'a')]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_dayin_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").dayin("a")).toString();
+ String parsed = parse("[?(@['a'] DAYIN ['a'])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_montheq_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").montheq("a")).toString();
+ String parsed = parse("[?(@['a'] MONTHEQ 'a')]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_monthin_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").monthin("a")).toString();
+ String parsed = parse("[?(@['a'] MONTHIN ['a'])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_yeareq_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").yeareq("a")).toString();
+ String parsed = parse("[?(@['a'] YEAREQ 'a')]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_yearin_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").yearin("a")).toString();
+ String parsed = parse("[?(@['a'] YEARIN ['a'])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_before_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").before("a")).toString();
+ String parsed = parse("[?(@['a'] BEFORE 'a')]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_after_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").after("a")).toString();
+ String parsed = parse("[?(@['a'] AFTER 'a')]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_houreq_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").houreq("a")).toString();
+ String parsed = parse("[?(@['a'] HOUREQ 'a')]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_hourin_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").hourin("a")).toString();
+ String parsed = parse("[?(@['a'] HOURIN ['a'])]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_timebefore_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").timebefore("a")).toString();
+ String parsed = parse("[?(@['a'] TIMEBEFORE 'a')]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_timeafter_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").timeafter("a")).toString();
+ String parsed = parse("[?(@['a'] TIMEAFTER 'a')]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_windowin_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").windowin("a")).toString();
+ String parsed = parse("[?(@['a'] WINDOWIN 'a')]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_windowout_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").windowout("a")).toString();
+ String parsed = parse("[?(@['a'] WINDOWOUT 'a')]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_windowtimein_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").windowtimein("a")).toString();
+ String parsed = parse("[?(@['a'] WINDOWTIMEIN 'a')]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
+
+ @Test
+ public void a_windowtimeout_objectrange_filter_can_be_serialized() {
+ String filter = filter(where("a").windowtimeout("a")).toString();
+ String parsed = parse("[?(@['a'] WINDOWTIMEOUT 'a')]").toString();
+ assertThat(filter).isEqualTo(parsed);
+ }
}