Browse Source

Simplified scanning impl.

pull/58/merge
Kalle Stenflo 10 years ago
parent
commit
ecc4631a0d
  1. 183
      json-path/src/main/java/com/jayway/jsonpath/internal/token/ScanPathToken.java

183
json-path/src/main/java/com/jayway/jsonpath/internal/token/ScanPathToken.java

@ -17,8 +17,6 @@ package com.jayway.jsonpath.internal.token;
import com.jayway.jsonpath.spi.json.JsonProvider;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
/**
*
@ -32,74 +30,64 @@ public class ScanPathToken extends PathToken {
ctx.addResult(currentPath, model);
}
Predicate predicate = createScanPredicate(next(), ctx);
Map<String, Object> predicateMatches = new LinkedHashMap<String, Object>();
PathToken pt = next();
walk(currentPath, model, ctx, predicate, predicateMatches);
//Filters has already been evaluated
PathToken next = next();
if (next instanceof PredicatePathToken) {
if (next.isLeaf()) {
for (Map.Entry<String, Object> match : predicateMatches.entrySet()) {
ctx.addResult(match.getKey(), match.getValue());
}
return;
} else {
next = next.next();
}
}
for (Map.Entry<String, Object> match : predicateMatches.entrySet()) {
next.evaluate(match.getKey(), match.getValue(), ctx);
}
walk(pt, currentPath, model, ctx, createScanPredicate(pt, ctx));
}
public static void walk(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map<String, Object> predicateMatches) {
public static void walk(PathToken pt, String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate) {
if (ctx.jsonProvider().isMap(model)) {
walkObject(currentPath, model, ctx, predicate, predicateMatches);
walkObject(pt, currentPath, model, ctx, predicate);
} else if (ctx.jsonProvider().isArray(model)) {
walkArray(currentPath, model, ctx, predicate, predicateMatches);
walkArray(pt, currentPath, model, ctx, predicate);
}
}
public static void walkArray(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map<String, Object> predicateMatches) {
public static void walkArray(PathToken pt, String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate) {
if (predicate.matches(model)) {
predicateMatches.put(currentPath, model);
if (pt.isLeaf()) {
pt.evaluate(currentPath, model, ctx);
} else {
PathToken next = pt.next();
Iterable<?> models = ctx.jsonProvider().toIterable(model);
int idx = 0;
for (Object evalModel : models) {
String evalPath = currentPath + "[" + idx + "]";
next.evaluate(evalPath, evalModel, ctx);
idx++;
}
}
}
Iterable<?> models = ctx.jsonProvider().toIterable(model);
int idx = 0;
for (Object evalModel : models) {
String evalPath = currentPath + "[" + idx + "]";
if (predicate.clazz().equals(PredicatePathToken.class)) {
if (predicate.matches(evalModel)) {
predicateMatches.put(evalPath, evalModel);
}
}
walk(evalPath, evalModel, ctx, predicate, predicateMatches);
walk(pt, evalPath, evalModel, ctx, predicate);
idx++;
}
}
public static void walkObject(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map<String, Object> predicateMatches) {
public static void walkObject(PathToken pt, String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate) {
if (predicate.matches(model)) {
predicateMatches.put(currentPath, model);
if (pt.isLeaf()) {
pt.evaluate(currentPath, model, ctx);
} else {
pt.evaluate(currentPath, model, ctx);
}
}
Collection<String> properties = ctx.jsonProvider().getPropertyKeys(model);
for (String property : properties) {
String evalPath = currentPath + "['" + property + "']";
Object propertyModel = ctx.jsonProvider().getMapValue(model, property);
if (propertyModel != JsonProvider.UNDEFINED) {
walk(evalPath, propertyModel, ctx, predicate, predicateMatches);
walk(pt, evalPath, propertyModel, ctx, predicate);
}
}
}
private static Predicate createScanPredicate(final PathToken target, final EvaluationContextImpl ctx) {
@ -128,94 +116,69 @@ public class ScanPathToken extends PathToken {
}
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;
}
@Override
public boolean matches(Object model) {
return false;
}
};
private static final class FilterPathTokenPredicate implements Predicate {
private final EvaluationContextImpl ctx;
private PredicatePathToken predicatePathToken;
private FilterPathTokenPredicate(PathToken target, EvaluationContextImpl ctx) {
this.ctx = ctx;
predicatePathToken = (PredicatePathToken) target;
}
@Override
public Class<?> clazz() {
return PredicatePathToken.class;
}
@Override
public boolean matches(Object model) {
return predicatePathToken.accept(model, ctx.rootDocument(), ctx.configuration(), ctx);
}
private final EvaluationContextImpl ctx;
private PredicatePathToken predicatePathToken;
private FilterPathTokenPredicate(PathToken target, EvaluationContextImpl ctx) {
this.ctx = ctx;
predicatePathToken = (PredicatePathToken) target;
}
@Override
public boolean matches(Object model) {
return predicatePathToken.accept(model, ctx.rootDocument(), ctx.configuration(), ctx);
}
}
private static final class WildcardPathTokenPredicate implements Predicate {
@Override
public Class<?> clazz() {
return WildcardPathToken.class;
}
@Override
public boolean matches(Object model) {
return true;
}
@Override
public boolean matches(Object model) {
return true;
}
}
private static final class ArrayPathTokenPredicate implements Predicate {
private final EvaluationContextImpl ctx;
private final EvaluationContextImpl ctx;
private ArrayPathTokenPredicate(EvaluationContextImpl ctx) {
this.ctx = ctx;
}
@Override
public Class<?> clazz() {
return ArrayPathToken.class;
}
private ArrayPathTokenPredicate(EvaluationContextImpl ctx) {
this.ctx = ctx;
}
@Override
public boolean matches(Object model) {
return ctx.jsonProvider().isArray(model);
}
@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) {
if(ctx.jsonProvider().isMap(model)){
Collection<String> keys = ctx.jsonProvider().getPropertyKeys(model);
return keys.containsAll(propertyPathToken.getProperties());
}
return false;
}
private final EvaluationContextImpl ctx;
private PropertyPathToken propertyPathToken;
private PropertyPathTokenPredicate(PathToken target, EvaluationContextImpl ctx) {
this.ctx = ctx;
propertyPathToken = (PropertyPathToken) target;
}
@Override
public boolean matches(Object model) {
if (ctx.jsonProvider().isMap(model)) {
Collection<String> keys = ctx.jsonProvider().getPropertyKeys(model);
return keys.containsAll(propertyPathToken.getProperties());
}
return false;
}
}
}

Loading…
Cancel
Save