Browse Source

Merge pull request #21 from jochenberger/performance-improvements

Performance improvements
pull/27/merge
kallestenflo 12 years ago
parent
commit
dedbf79394
  1. 27
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java
  2. 27
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayIndexFilter.java
  3. 6
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/FieldFilter.java
  4. 19
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/HasFieldFilter.java
  5. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/PathTokenFilter.java
  6. 144
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/eval/ExpressionEvaluator.java

27
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<Object> src = jsonProvider.toList(obj);
List<Object> 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<Object> src = jsonProvider.toList(obj);
List<Object> 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;
}
}

27
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<Object> src = jsonProvider.toList(obj);
List<Object> 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;

6
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<String, Object> 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<String, Object> map = jsonProvider.toMap(obj);
if(!map.containsKey(condition) && split.length == 1){

19
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<Object> src = jsonProvider.toList(obj);
List<Object> 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<String, Object> map = jsonProvider.toMap(item);

2
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) {

144
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 <T> boolean eval(T actual, String comparator, String expected) {
private Operator(String representation) {
this.representation = representation;
}
public String getRepresentation() {
return representation;
}
}
private static Map<String, Operator> operatorsByRepresentation;
static {
Map<String, Operator> map = new HashMap<String, Operator>();
for (Operator op : Operator.values()){
map.put(op.getRepresentation(), op);
}
ExpressionEvaluator.operatorsByRepresentation = Collections.unmodifiableMap(map);
}
public static <T> 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;
}
}

Loading…
Cancel
Save