diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java index 0393b0b5..d72fb00f 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java @@ -29,16 +29,11 @@ import java.util.regex.Pattern; public class ArrayEvalFilter extends PathTokenFilter { private static final Pattern PATTERN = Pattern.compile("(.*?)\\s?([=<>]+)\\s?(.*)"); + private final ConditionStatement conditionStatement; public ArrayEvalFilter(String condition) { super(condition); - } - - @Override - public Object filter(Object obj, JsonProvider jsonProvider) { //[?(@.isbn == 10)] - List src = jsonProvider.toList(obj); - List result = jsonProvider.createList(); String trimmedCondition = condition; @@ -49,7 +44,13 @@ public class ArrayEvalFilter extends PathTokenFilter { trimmedCondition = trim(trimmedCondition, 5, 2); - ConditionStatement conditionStatement = createConditionStatement(trimmedCondition); + this.conditionStatement = createConditionStatement(trimmedCondition); + } + + @Override + public Object filter(Object obj, JsonProvider jsonProvider) { + List src = jsonProvider.toList(obj); + List result = jsonProvider.createList(); for (Object item : src) { if (isMatch(item, conditionStatement, jsonProvider)) { @@ -101,18 +102,20 @@ public class ArrayEvalFilter extends PathTokenFilter { } } - private class ConditionStatement { + private static class ConditionStatement { private final String field; private final String operator; - private String expected; + private final String expected; private ConditionStatement(String field, String operator, String expected) { this.field = field; this.operator = operator.trim(); - this.expected = expected; + - if(this.expected.startsWith("'")){ - this.expected = trim(this.expected, 1, 1); + if(expected.startsWith("'")){ + this.expected = trim(expected, 1, 1); + }else{ + this.expected = expected; } } diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayIndexFilter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayIndexFilter.java index c7ccc070..aa4ab526 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayIndexFilter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayIndexFilter.java @@ -25,9 +25,22 @@ import java.util.regex.Pattern; public class ArrayIndexFilter extends PathTokenFilter { private static final Pattern SINGLE_ARRAY_INDEX_PATTERN = Pattern.compile("\\[\\d+\\]"); + private static final Pattern COMMA = Pattern.compile(","); + private static final Pattern SPACE = Pattern.compile(" "); + + + private final String trimmedCondition; public ArrayIndexFilter(String condition) { super(condition); + String trimmedCondition = trim(condition, 1, 1); + + if(trimmedCondition.contains("@.length")){ + trimmedCondition = trim(trimmedCondition, 1, 1); + trimmedCondition = trimmedCondition.replace("@.length", ""); + trimmedCondition = trimmedCondition + ":"; + } + this.trimmedCondition = trimmedCondition; } @Override @@ -36,17 +49,11 @@ public class ArrayIndexFilter extends PathTokenFilter { List src = jsonProvider.toList(obj); List result = jsonProvider.createList(); - String trimmedCondition = trim(condition, 1, 1); - - if(trimmedCondition.contains("@.length")){ - trimmedCondition = trim(trimmedCondition, 1, 1); - trimmedCondition = trimmedCondition.replace("@.length", ""); - trimmedCondition = trimmedCondition + ":"; - } + if (trimmedCondition.startsWith(":")) { - trimmedCondition = trim(trimmedCondition, 1, 0); + String trimmedCondition = trim(this.trimmedCondition, 1, 0); int get = Integer.parseInt(trimmedCondition); for (int i = 0; i < get; i++) { result.add(src.get(i)); @@ -54,12 +61,12 @@ public class ArrayIndexFilter extends PathTokenFilter { return result; } else if (trimmedCondition.endsWith(":")) { - trimmedCondition = trim(trimmedCondition.replace(" ", ""), 1, 1); + String trimmedCondition = trim(SPACE.matcher(this.trimmedCondition).replaceAll(""), 1, 1); int get = Integer.parseInt(trimmedCondition); return src.get(src.size() - get); } else { - String[] indexArr = trimmedCondition.split(","); + String[] indexArr = COMMA.split(trimmedCondition); if(src.isEmpty()){ return result; diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FieldFilter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FieldFilter.java index 13a5998f..7dbda68c 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FieldFilter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FieldFilter.java @@ -27,8 +27,11 @@ import java.util.Map; */ public class FieldFilter extends PathTokenFilter { + private final String[] split; + public FieldFilter(String condition) { super(condition); + this.split = condition.split("','"); } @Override @@ -43,7 +46,7 @@ public class FieldFilter extends PathTokenFilter { Map map = jsonProvider.toMap(current); - String[] split = condition.split("','"); + if(split.length == 1){ if (map.containsKey(condition)) { Object o = map.get(condition); @@ -67,7 +70,6 @@ public class FieldFilter extends PathTokenFilter { return result; } } else { - String[] split = condition.split("','"); Map map = jsonProvider.toMap(obj); if(!map.containsKey(condition) && split.length == 1){ diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/HasFieldFilter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/HasFieldFilter.java index 272f1ea4..7a6b62d9 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/HasFieldFilter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/HasFieldFilter.java @@ -24,8 +24,18 @@ import java.util.Map; */ public class HasFieldFilter extends PathTokenFilter { + private final String trimmedCondition; + public HasFieldFilter(String condition) { super(condition); + String trimmedCondition = condition; + + if(condition.contains("['")){ + trimmedCondition = trimmedCondition.replace("['", "."); + trimmedCondition = trimmedCondition.replace("']", ""); + } + + this.trimmedCondition = trim(trimmedCondition, 5, 2); } @Override @@ -35,15 +45,6 @@ public class HasFieldFilter extends PathTokenFilter { List src = jsonProvider.toList(obj); List result = jsonProvider.createList(); - String trimmedCondition = condition; - - if(condition.contains("['")){ - trimmedCondition = trimmedCondition.replace("['", "."); - trimmedCondition = trimmedCondition.replace("']", ""); - } - - trimmedCondition = trim(trimmedCondition, 5, 2); - for (Object item : src) { if(jsonProvider.isMap(item)){ Map map = jsonProvider.toMap(item); diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/PathTokenFilter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/PathTokenFilter.java index 9b0af8d2..1026e6f6 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/PathTokenFilter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/PathTokenFilter.java @@ -34,7 +34,7 @@ public abstract class PathTokenFilter { return condition; } - String trim(String str, int front, int end) { + static String trim(String str, int front, int end) { String res = str; if (front > 0) { diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/eval/ExpressionEvaluator.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/eval/ExpressionEvaluator.java index e6077537..a781e153 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/eval/ExpressionEvaluator.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/eval/ExpressionEvaluator.java @@ -14,93 +14,159 @@ */ package com.jayway.jsonpath.internal.filter.eval; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + /** * @author Kalle Stenflo */ public class ExpressionEvaluator { + + + public enum Operator { + equal("=="), not_equal("!="), less_or_greater_than("<>"),greater_than(">"), greater_than_or_equal(">="), less_than("<"), less_than_or_equal("<="); + + private final String representation; - public static boolean eval(T actual, String comparator, String expected) { + private Operator(String representation) { + this.representation = representation; + } + + public String getRepresentation() { + return representation; + } + } + + private static Map operatorsByRepresentation; + + static { + Map map = new HashMap(); + for (Operator op : Operator.values()){ + map.put(op.getRepresentation(), op); + } + ExpressionEvaluator.operatorsByRepresentation = Collections.unmodifiableMap(map); + } + + public static boolean eval(T actual, String comparator, String expected) { + + Operator operator = operatorsByRepresentation.get(comparator); + if (operator == null){ + throw new IllegalArgumentException("Unsupported operator " + comparator); + } + if (actual instanceof Long) { Long a = (Long) actual; Long e = Long.parseLong(expected.trim()); - - if ("==".equals(comparator)) { + switch (operator){ + case equal: return a.longValue() == e.longValue(); - } else if ("!=".equals(comparator) || "<>".equals(comparator)) { + case not_equal: + case less_or_greater_than: return a.longValue() != e.longValue(); - } else if (">".equals(comparator)) { + case greater_than: return a > e; - } else if (">=".equals(comparator)) { + case greater_than_or_equal: return a >= e; - } else if ("<".equals(comparator)) { + case less_than: return a < e; - } else if ("<=".equals(comparator)) { + case less_than_or_equal: return a <= e; + default: + throw new UnsupportedOperationException("Cannot handle operator " + operator); } + + } else if (actual instanceof Integer) { Integer a = (Integer) actual; Integer e = Integer.parseInt(expected.trim()); - if ("==".equals(comparator)) { + switch (operator){ + case equal: return a.intValue() == e.intValue(); - } else if ("!=".equals(comparator) || "<>".equals(comparator)) { + case not_equal: + case less_or_greater_than: return a.intValue() != e.intValue(); - } else if (">".equals(comparator)) { + case greater_than: return a > e; - } else if (">=".equals(comparator)) { + case greater_than_or_equal: return a >= e; - } else if ("<".equals(comparator)) { + case less_than: return a < e; - } else if ("<=".equals(comparator)) { + case less_than_or_equal: return a <= e; + default: + throw new UnsupportedOperationException("Cannot handle operator " + operator); } } else if (actual instanceof Double) { Double a = (Double) actual; Double e = Double.parseDouble(expected.trim()); - if ("==".equals(comparator)) { + switch (operator){ + case equal: return a.doubleValue() == e.doubleValue(); - } else if ("!=".equals(comparator) || "<>".equals(comparator)) { + case not_equal: + case less_or_greater_than: return a.doubleValue() != e.doubleValue(); - } else if (">".equals(comparator)) { + case greater_than: return a > e; - } else if (">=".equals(comparator)) { + case greater_than_or_equal: return a >= e; - } else if ("<".equals(comparator)) { + case less_than: return a < e; - } else if ("<=".equals(comparator)) { + case less_than_or_equal: return a <= e; + default: + throw new UnsupportedOperationException("Cannot handle operator " + operator); } } else if (actual instanceof String) { - String a = (String)actual; - expected = expected.trim(); - if(expected.startsWith("'")) { - expected = expected.substring(1); - } - if(expected.endsWith("'")){ - expected = expected.substring(0, expected.length()-1); - } + switch (operator){ + case greater_than: + case greater_than_or_equal: + case less_than: + case less_than_or_equal: + // we might want to throw an exception here + return false; + case equal: + case not_equal: + case less_or_greater_than: + String a = (String)actual; + String expectedTrimmed = expected.trim(); + if(expectedTrimmed.startsWith("'")) { + expectedTrimmed = expectedTrimmed.substring(1); + } + if(expectedTrimmed.endsWith("'")){ + expectedTrimmed = expectedTrimmed.substring(0, expected.length()-1); + } - if ("==".equals(comparator)) { - return a.equals(expected); - } else if ("!=".equals(comparator) || "<>".equals(comparator)) { - return !a.equals(expected); - } + if (operator == Operator.equal) { + return a.equals(expectedTrimmed); + } else if (operator == Operator.not_equal || operator == Operator.less_or_greater_than) { + return !a.equals(expectedTrimmed); + } + default: + throw new UnsupportedOperationException("Cannot handle operator " + operator); + } } else if (actual instanceof Boolean) { - - Boolean a = (Boolean) actual; - Boolean e = Boolean.valueOf(expected); - if ("==".equals(comparator)) { + switch (operator){ + case equal: + case not_equal: + case less_or_greater_than: + Boolean a = (Boolean) actual; + Boolean e = Boolean.valueOf(expected); + if (operator == Operator.equal) { return a.equals(e); - } else if ("!=".equals(comparator) || "<>".equals(comparator)) { + } else if (operator == Operator.not_equal || operator == Operator.less_or_greater_than) { return !a.equals(e); } + default: + throw new UnsupportedOperationException("Cannot handle operator " + operator); + } } - return false; } }