Browse Source

Anyof criteria fixed, ZonedDateTime Support, Multiple Filters for date and time, Number List filters for list to list comparison, Right to left filters for subset, anyof, noneof and all.

pull/796/head
vaobhav1993 3 years ago
parent
commit
5fcde2a675
  1. 543
      json-path/src/main/java/com/jayway/jsonpath/Criteria.java
  2. 723
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java
  3. 32
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/RelationalOperator.java
  4. 15
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java
  5. 66
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java
  6. 265
      json-path/src/test/java/com/jayway/jsonpath/FilterParseTest.java

543
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 <b>&ltall;</b> operator
*
* @param o
* @return the criteria
*/
public Criteria ltall(Object... o) {
return ltall(Arrays.asList(o));
}
/**
* Creates a criterion using the <b>&ltall;</b> 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 <b>&lteall;</b> operator
*
* @param o
* @return the criteria
*/
public Criteria lteall(Object... o) {
return lteall(Arrays.asList(o));
}
/**
* Creates a criterion using the <b>&lteall;</b> 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 <b>&ltany;</b> operator
*
* @param o
* @return the criteria
*/
public Criteria ltany(Object... o) {
return ltany(Arrays.asList(o));
}
/**
* Creates a criterion using the <b>&ltany;</b> 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 <b>&lteany;</b> operator
*
* @param o
* @return the criteria
*/
public Criteria lteany(Object... o) {
return lteany(Arrays.asList(o));
}
/**
* Creates a criterion using the <b>&lteany;</b> 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 <b>&lt;=</b> operator
*
@ -181,6 +269,94 @@ public class Criteria implements Predicate {
return this;
}
/**
* Creates a criterion using the <b>&gtall;</b> operator
*
* @param o
* @return the criteria
*/
public Criteria gtall(Object... o) {
return gtall(Arrays.asList(o));
}
/**
* Creates a criterion using the <b>&gtall;</b> 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 <b>&gteall;</b> operator
*
* @param o
* @return the criteria
*/
public Criteria gteall(Object... o) {
return gteall(Arrays.asList(o));
}
/**
* Creates a criterion using the <b>&gteall;</b> 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 <b>&gtany;</b> operator
*
* @param o
* @return the criteria
*/
public Criteria gtany(Object... o) {
return gtany(Arrays.asList(o));
}
/**
* Creates a criterion using the <b>&gtany;</b> 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 <b>&gteany;</b> operator
*
* @param o
* @return the criteria
*/
public Criteria gteany(Object... o) {
return gteany(Arrays.asList(o));
}
/**
* Creates a criterion using the <b>&gteany;</b> 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 <b>&gt;=</b> 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 <b>&dateeq;</b> 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 <b>&dayeq;</b> 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 <b>&montheq;</b> 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 <b>&yeareq;</b> 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 <b>&dayin;</b> operator
*
* @param o
* @return the criteria
*/
public Criteria dayin(Object... o) {
return dayin(Arrays.asList(o));
}
/**
* Creates a criterion using the <b>&dayin;</b> 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 <b>&monthin;</b> operator
*
* @param o
* @return the criteria
*/
public Criteria monthin(Object... o) {
return monthin(Arrays.asList(o));
}
/**
* Creates a criterion using the <b>&monthin;</b> 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 <b>&yearin;</b> operator
*
* @param o
* @return the criteria
*/
public Criteria yearin(Object... o) {
return yearin(Arrays.asList(o));
}
/**
* Creates a criterion using the <b>&yearin;</b> 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 <b>&before;</b> 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 <b>&after;</b> 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 <b>&houreq;</b> 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 <b>&hourin;</b> operator
*
* @param o
* @return the criteria
*/
public Criteria hourin(Object... o) {
return hourin(Arrays.asList(o));
}
/**
* Creates a criterion using the <b>&hourin;</b> 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 <b>&timebefore;</b> 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 <b>&timeafter;</b> operator
*
* @param o
* @return the criteria
*/
public Criteria timeafter(Object o) {
this.criteriaType = RelationalOperator.TIMEAFTER;
this.right = ValueNode.toValueNode(o);
return this;
}
/**
* The <code>allmatch</code> 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 <code>allmatch</code> 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 <code>anymatch</code> 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 <code>anymatch</code> 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 <code>nonematch</code> 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 <code>nonematch</code> 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 <code>exactmatch</code> 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 <code>exactmatch</code> 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 <b>&windowin;</b> 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 <b>&windowout;</b> 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 <b>&windowtimein;</b> 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 <b>&windowtimeout;</b> operator
*
* @param o
* @return the criteria
*/
public Criteria windowtimeout(Object o) {
this.criteriaType = RelationalOperator.WINDOWTIMEOUT;
this.right = ValueNode.toValueNode(o);
return this;
}
/**
* The <code>notcontains</code> 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 <code>size</code> operator matches:
* <p/>

723
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,6 +43,36 @@ 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) {
@ -98,29 +136,185 @@ public class EvaluatorFactory {
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
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()) {
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) {
@ -135,6 +329,82 @@ public class EvaluatorFactory {
}
}
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) {
@ -149,6 +419,82 @@ public class EvaluatorFactory {
}
}
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) {
@ -233,8 +579,23 @@ public class EvaluatorFactory {
ValueNode valueNode = left.asJsonNode().asValueListNode(ctx);
if (valueNode.isUndefinedNode()) return false;
else {
boolean res = valueNode.asValueListNode().contains(right);
return res;
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;
else {
return !(valueNode.asValueListNode().contains(right));
}
}
return false;
@ -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);
}
}
}

32
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;

15
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;

66
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;

265
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);
}
}

Loading…
Cancel
Save