From 2664f831045542b79b3b2af0b3f6055e892e2aa8 Mon Sep 17 00:00:00 2001 From: Jochen Berger Date: Fri, 12 Sep 2014 14:39:22 +0200 Subject: [PATCH] merge JsonProvider's getMapValue methods, various small performance improvements --- .../jsonpath/internal/compiler/PathToken.java | 6 +- .../internal/compiler/ScanPathToken.java | 168 +++++++++++------- .../spi/json/AbstractJsonProvider.java | 16 +- .../jsonpath/spi/json/JsonProvider.java | 12 +- 4 files changed, 105 insertions(+), 97 deletions(-) diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/compiler/PathToken.java b/json-path/src/main/java/com/jayway/jsonpath/internal/compiler/PathToken.java index 79b7e081..89dad21f 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/compiler/PathToken.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/compiler/PathToken.java @@ -69,12 +69,12 @@ public abstract class PathToken { } } - private boolean hasProperty(String property, Object model, EvaluationContextImpl ctx) { + private static boolean hasProperty(String property, Object model, EvaluationContextImpl ctx) { return ctx.jsonProvider().getPropertyKeys(model).contains(property); } - private Object readObjectProperty(String property, Object model, EvaluationContextImpl ctx) { - return ctx.jsonProvider().getMapValue(model, property, true); + private static Object readObjectProperty(String property, Object model, EvaluationContextImpl ctx) { + return ctx.jsonProvider().getMapValue(model, property); } void handleArrayIndex(int index, String currentPath, Object json, EvaluationContextImpl ctx) { diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/compiler/ScanPathToken.java b/json-path/src/main/java/com/jayway/jsonpath/internal/compiler/ScanPathToken.java index 75f91592..e7014b5c 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/compiler/ScanPathToken.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/compiler/ScanPathToken.java @@ -4,6 +4,8 @@ import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; +import com.jayway.jsonpath.spi.json.JsonProvider; + /** * */ @@ -39,7 +41,7 @@ public class ScanPathToken extends PathToken { } } - public void walk(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map predicateMatches) { + public static void walk(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map predicateMatches) { if (ctx.jsonProvider().isMap(model)) { walkObject(currentPath, model, ctx, predicate, predicateMatches); } else if (ctx.jsonProvider().isArray(model)) { @@ -47,7 +49,7 @@ public class ScanPathToken extends PathToken { } } - public void walkArray(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map predicateMatches) { + public static void walkArray(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map predicateMatches) { if (predicate.matches(model)) { predicateMatches.put(currentPath, model); @@ -69,7 +71,7 @@ public class ScanPathToken extends PathToken { } } - public void walkObject(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map predicateMatches) { + public static void walkObject(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map predicateMatches) { if (predicate.matches(model)) { predicateMatches.put(currentPath, model); @@ -79,79 +81,24 @@ public class ScanPathToken extends PathToken { for (String property : properties) { String evalPath = currentPath + "['" + property + "']"; Object propertyModel = ctx.jsonProvider().getMapValue(model, property); - walk(evalPath, propertyModel, ctx, predicate, predicateMatches); + if (propertyModel != JsonProvider.UNDEFINED) { + walk(evalPath, propertyModel, ctx, predicate, predicateMatches); + } } } - private Predicate createScanPredicate(final PathToken target, final EvaluationContextImpl ctx) { + private static Predicate createScanPredicate(final PathToken target, final EvaluationContextImpl ctx) { if (target instanceof PropertyPathToken) { - return new Predicate() { - private PropertyPathToken propertyPathToken = (PropertyPathToken) target; - - @Override - public Class clazz() { - return PropertyPathToken.class; - } - - @Override - public boolean matches(Object model) { - Collection keys = ctx.jsonProvider().getPropertyKeys(model); - return keys.containsAll(propertyPathToken.getProperties()); - } - }; + return new PropertyPathTokenPredicate(target, ctx); } else if (target instanceof ArrayPathToken) { - return new Predicate() { - - @Override - public Class clazz() { - return ArrayPathToken.class; - } - - @Override - public boolean matches(Object model) { - return ctx.jsonProvider().isArray(model); - } - }; + return new ArrayPathTokenPredicate(ctx); } else if (target instanceof WildcardPathToken) { - return new Predicate() { - - @Override - public Class clazz() { - return WildcardPathToken.class; - } - - @Override - public boolean matches(Object model) { - return true; - } - }; + return new WildcardPathTokenPredicate(); } else if (target instanceof FilterPathToken) { - return new Predicate() { - private FilterPathToken filterPathToken = (FilterPathToken) target; - - @Override - public Class clazz() { - return FilterPathToken.class; - } - - @Override - public boolean matches(Object model) { - return filterPathToken.accept(model, ctx.configuration()); - } - }; + return new FilterPathTokenPredicate(target, ctx); } else { - return new Predicate() { - @Override - public Class clazz() { - return null; - } - - @Override - public boolean matches(Object model) { - return false; - } - }; + return FALSE_PREDICATE; } } @@ -165,10 +112,93 @@ public class ScanPathToken extends PathToken { public String getPathFragment() { return ".."; } - - private interface Predicate { + + private static interface Predicate { Class clazz(); boolean matches(Object model); } + + private static final Predicate FALSE_PREDICATE = new Predicate() { + @Override + public Class clazz() { + return null; + } + + @Override + public boolean matches(Object model) { + return false; + } + }; + + private static final class FilterPathTokenPredicate implements Predicate { + private final EvaluationContextImpl ctx; + private FilterPathToken filterPathToken; + + private FilterPathTokenPredicate(PathToken target, EvaluationContextImpl ctx) { + this.ctx = ctx; + filterPathToken = (FilterPathToken) target; + } + + @Override + public Class clazz() { + return FilterPathToken.class; + } + + @Override + public boolean matches(Object model) { + return filterPathToken.accept(model, ctx.configuration()); + } + } + + private static final class WildcardPathTokenPredicate implements Predicate { + @Override + public Class clazz() { + return WildcardPathToken.class; + } + + @Override + public boolean matches(Object model) { + return true; + } + } + + private static final class ArrayPathTokenPredicate implements Predicate { + private final EvaluationContextImpl ctx; + + private ArrayPathTokenPredicate(EvaluationContextImpl ctx) { + this.ctx = ctx; + } + + @Override + public Class clazz() { + return ArrayPathToken.class; + } + + @Override + public boolean matches(Object model) { + return ctx.jsonProvider().isArray(model); + } + } + + private static final class PropertyPathTokenPredicate implements Predicate { + private final EvaluationContextImpl ctx; + private PropertyPathToken propertyPathToken; + + private PropertyPathTokenPredicate(PathToken target, EvaluationContextImpl ctx) { + this.ctx = ctx; + propertyPathToken = (PropertyPathToken) target; + } + + @Override + public Class clazz() { + return PropertyPathToken.class; + } + + @Override + public boolean matches(Object model) { + Collection keys = ctx.jsonProvider().getPropertyKeys(model); + return keys.containsAll(propertyPathToken.getProperties()); + } + } } diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/AbstractJsonProvider.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/AbstractJsonProvider.java index 226b9a07..d43b98d4 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/AbstractJsonProvider.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/AbstractJsonProvider.java @@ -50,23 +50,11 @@ public abstract class AbstractJsonProvider implements JsonProvider { * * @param obj a map * @param key property key - * @return the map entry + * @return the map entry or {@link com.jayway.jsonpath.spi.json.JsonProvider#UNDEFINED} for missing properties */ public Object getMapValue(Object obj, String key){ - return ((Map) obj).get(key); - } - - /** - * Extracts a value from an map - * - * @param obj a map - * @param key property key - * @param signalUndefined if true the constant {@link com.jayway.jsonpath.spi.json.JsonProvider#UNDEFINED} is returned for missing properties - * @return the map entry - */ - public Object getMapValue(Object obj, String key, boolean signalUndefined){ Map m = (Map) obj; - if(!m.containsKey(key) && signalUndefined){ + if(!m.containsKey(key)){ return JsonProvider.UNDEFINED; } else { return m.get(key); diff --git a/json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java b/json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java index 61da8b36..67ca5ed6 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java +++ b/json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java @@ -83,20 +83,10 @@ public interface JsonProvider { * * @param obj a map * @param key property key - * @return the map entry + * @return the map entry or {@link com.jayway.jsonpath.spi.json.JsonProvider#UNDEFINED} for missing properties */ Object getMapValue(Object obj, String key); - /** - * Extracts a value from an map - * - * @param obj a map - * @param key property key - * @param signalUndefined if true the constant {@link com.jayway.jsonpath.spi.json.JsonProvider#UNDEFINED} is returned for missing properties - * @return the map entry - */ - Object getMapValue(Object obj, String key, boolean signalUndefined); - /** * Sets a value in an object or array *