Browse Source

Various warning clean-ups from IntelliJ

Split ValueNode into a separate class to avoid possible race-condition in class loading.

Modified ArrayPathToken to be super-class of ArrayIndex/ArraySlice token
because IntelliJ warned about null pointer exception possibilities.

Removed redundant boolean checks.

Removed use of StringBuffer -> StringBuilder.

Removed dangling ;
pull/416/head
Elias Ross 7 years ago
parent
commit
bb0853fb5e
  1. 16
      json-path/src/main/java/com/jayway/jsonpath/Criteria.java
  2. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java
  3. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/DefaultsImpl.java
  4. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/PathRef.java
  5. 8
      json-path/src/main/java/com/jayway/jsonpath/internal/Utils.java
  6. 13
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java
  7. 19
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java
  8. 653
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java
  9. 662
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java
  10. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/function/text/Concatenate.java
  11. 52
      json-path/src/main/java/com/jayway/jsonpath/internal/path/ArrayIndexToken.java
  12. 138
      json-path/src/main/java/com/jayway/jsonpath/internal/path/ArrayPathToken.java
  13. 18
      json-path/src/main/java/com/jayway/jsonpath/internal/path/ArraySliceOperation.java
  14. 114
      json-path/src/main/java/com/jayway/jsonpath/internal/path/ArraySliceToken.java
  15. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/path/CompiledPath.java
  16. 4
      json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java
  17. 4
      json-path/src/main/java/com/jayway/jsonpath/internal/path/PathTokenFactory.java
  18. 3
      json-path/src/main/java/com/jayway/jsonpath/internal/path/PredicatePathToken.java
  19. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/path/RootPathToken.java
  20. 4
      json-path/src/main/java/com/jayway/jsonpath/internal/path/WildcardPathToken.java
  21. 2
      json-path/src/main/java/com/jayway/jsonpath/spi/cache/CacheProvider.java
  22. 2
      json-path/src/main/java/com/jayway/jsonpath/spi/json/AbstractJsonProvider.java
  23. 3
      json-path/src/test/java/com/jayway/jsonpath/FilterTest.java

16
json-path/src/main/java/com/jayway/jsonpath/Criteria.java

@ -28,7 +28,9 @@ import java.util.List;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static com.jayway.jsonpath.internal.Utils.notNull; import static com.jayway.jsonpath.internal.Utils.notNull;
import com.jayway.jsonpath.internal.filter.ValueNodes;
import static com.jayway.jsonpath.internal.filter.ValueNodes.ValueListNode;
import static com.jayway.jsonpath.internal.filter.ValueNodes.PredicateNode;
/** /**
* *
@ -225,7 +227,7 @@ public class Criteria implements Predicate {
public Criteria in(Collection<?> c) { public Criteria in(Collection<?> c) {
notNull(c, "collection can not be null"); notNull(c, "collection can not be null");
this.criteriaType = RelationalOperator.IN; this.criteriaType = RelationalOperator.IN;
this.right = new ValueNode.ValueListNode(c); this.right = new ValueListNode(c);
return this; return this;
} }
@ -263,7 +265,7 @@ public class Criteria implements Predicate {
public Criteria nin(Collection<?> c) { public Criteria nin(Collection<?> c) {
notNull(c, "collection can not be null"); notNull(c, "collection can not be null");
this.criteriaType = RelationalOperator.NIN; this.criteriaType = RelationalOperator.NIN;
this.right = new ValueNode.ValueListNode(c); this.right = new ValueListNode(c);
return this; return this;
} }
@ -290,7 +292,7 @@ public class Criteria implements Predicate {
public Criteria subsetof(Collection<?> c) { public Criteria subsetof(Collection<?> c) {
notNull(c, "collection can not be null"); notNull(c, "collection can not be null");
this.criteriaType = RelationalOperator.SUBSETOF; this.criteriaType = RelationalOperator.SUBSETOF;
this.right = new ValueNode.ValueListNode(c); this.right = new ValueListNode(c);
return this; return this;
} }
@ -315,7 +317,7 @@ public class Criteria implements Predicate {
public Criteria all(Collection<?> c) { public Criteria all(Collection<?> c) {
notNull(c, "collection can not be null"); notNull(c, "collection can not be null");
this.criteriaType = RelationalOperator.ALL; this.criteriaType = RelationalOperator.ALL;
this.right = new ValueNode.ValueListNode(c); this.right = new ValueListNode(c);
return this; return this;
} }
@ -389,7 +391,7 @@ public class Criteria implements Predicate {
*/ */
public Criteria empty(boolean empty) { public Criteria empty(boolean empty) {
this.criteriaType = RelationalOperator.EMPTY; this.criteriaType = RelationalOperator.EMPTY;
this.right = empty ? ValueNode.TRUE : ValueNode.FALSE; this.right = empty ? ValueNodes.TRUE : ValueNodes.FALSE;
return this; return this;
} }
@ -401,7 +403,7 @@ public class Criteria implements Predicate {
*/ */
public Criteria matches(Predicate p) { public Criteria matches(Predicate p) {
this.criteriaType = RelationalOperator.MATCHES; this.criteriaType = RelationalOperator.MATCHES;
this.right = new ValueNode.PredicateNode(p); this.right = new PredicateNode(p);
return this; return this;
} }

2
json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java

@ -172,7 +172,7 @@ public class CharacterIndex {
inEscape = false; inEscape = false;
} else if('\\' == charAt(readPosition)){ } else if('\\' == charAt(readPosition)){
inEscape = true; inEscape = true;
} else if (c == charAt(readPosition) && !inEscape){ } else if (c == charAt(readPosition)){
return readPosition; return readPosition;
} }
readPosition ++; readPosition ++;

2
json-path/src/main/java/com/jayway/jsonpath/internal/DefaultsImpl.java

@ -32,6 +32,6 @@ public final class DefaultsImpl implements Defaults {
} }
private DefaultsImpl() { private DefaultsImpl() {
}; }
} }

2
json-path/src/main/java/com/jayway/jsonpath/internal/PathRef.java

@ -212,7 +212,7 @@ public abstract class PathRef implements Comparable<PathRef> {
public int compareTo(PathRef o) { public int compareTo(PathRef o) {
if(o instanceof ArrayIndexPathRef){ if(o instanceof ArrayIndexPathRef){
ArrayIndexPathRef pf = (ArrayIndexPathRef) o; ArrayIndexPathRef pf = (ArrayIndexPathRef) o;
return Integer.valueOf(pf.index).compareTo(this.index); return Integer.compare(pf.index, this.index);
} }
return super.compareTo(o); return super.compareTo(o);
} }

8
json-path/src/main/java/com/jayway/jsonpath/internal/Utils.java

@ -24,8 +24,8 @@ import java.util.Iterator;
public final class Utils { public final class Utils {
// accept a collection of objects, since all objects have toString() // accept a collection of objects, since all objects have toString()
public static String join(String delimiter, String wrap, Iterable<? extends Object> objs) { public static String join(String delimiter, String wrap, Iterable<?> objs) {
Iterator<? extends Object> iter = objs.iterator(); Iterator<?> iter = objs.iterator();
if (!iter.hasNext()) { if (!iter.hasNext()) {
return ""; return "";
} }
@ -38,7 +38,7 @@ public final class Utils {
} }
// accept a collection of objects, since all objects have toString() // accept a collection of objects, since all objects have toString()
public static String join(String delimiter, Iterable<? extends Object> objs) { public static String join(String delimiter, Iterable<?> objs) {
return join(delimiter, "", objs); return join(delimiter, "", objs);
} }
@ -175,7 +175,7 @@ public final class Utils {
} }
int len = str.length(); int len = str.length();
StringWriter writer = new StringWriter(len); StringWriter writer = new StringWriter(len);
StringBuffer unicode = new StringBuffer(4); StringBuilder unicode = new StringBuilder(4);
boolean hadSlash = false; boolean hadSlash = false;
boolean inUnicode = false; boolean inUnicode = false;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {

13
json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java

@ -2,6 +2,7 @@ package com.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.JsonPathException; import com.jayway.jsonpath.JsonPathException;
import com.jayway.jsonpath.Predicate; import com.jayway.jsonpath.Predicate;
import static com.jayway.jsonpath.internal.filter.ValueNodes.*;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -168,7 +169,7 @@ public class EvaluatorFactory {
private static class InEvaluator implements Evaluator { private static class InEvaluator implements Evaluator {
@Override @Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) { public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
ValueNode.ValueListNode valueListNode; ValueListNode valueListNode;
if(right.isJsonNode()){ if(right.isJsonNode()){
ValueNode vn = right.asJsonNode().asValueListNode(ctx); ValueNode vn = right.asJsonNode().asValueListNode(ctx);
if(vn.isUndefinedNode()){ if(vn.isUndefinedNode()){
@ -193,12 +194,12 @@ public class EvaluatorFactory {
private static class AllEvaluator implements Evaluator { private static class AllEvaluator implements Evaluator {
@Override @Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) { public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
ValueNode.ValueListNode requiredValues = right.asValueListNode(); ValueListNode requiredValues = right.asValueListNode();
if(left.isJsonNode()){ if(left.isJsonNode()){
ValueNode valueNode = left.asJsonNode().asValueListNode(ctx); //returns UndefinedNode if conversion is not possible ValueNode valueNode = left.asJsonNode().asValueListNode(ctx); //returns UndefinedNode if conversion is not possible
if(valueNode.isValueListNode()){ if(valueNode.isValueListNode()){
ValueNode.ValueListNode shouldContainAll = valueNode.asValueListNode(); ValueListNode shouldContainAll = valueNode.asValueListNode();
for (ValueNode required : requiredValues) { for (ValueNode required : requiredValues) {
if(!shouldContainAll.contains(required)){ if(!shouldContainAll.contains(required)){
return false; return false;
@ -249,7 +250,7 @@ public class EvaluatorFactory {
} }
} }
private boolean matches(ValueNode.PatternNode patternNode, String inputToMatch) { private boolean matches(PatternNode patternNode, String inputToMatch) {
return patternNode.getCompiledPattern().matcher(inputToMatch).matches(); return patternNode.getCompiledPattern().matcher(inputToMatch).matches();
} }
@ -269,7 +270,7 @@ public class EvaluatorFactory {
private static class SubsetOfEvaluator implements Evaluator { private static class SubsetOfEvaluator implements Evaluator {
@Override @Override
public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) { public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {
ValueNode.ValueListNode rightValueListNode; ValueListNode rightValueListNode;
if(right.isJsonNode()){ if(right.isJsonNode()){
ValueNode vn = right.asJsonNode().asValueListNode(ctx); ValueNode vn = right.asJsonNode().asValueListNode(ctx);
if(vn.isUndefinedNode()){ if(vn.isUndefinedNode()){
@ -280,7 +281,7 @@ public class EvaluatorFactory {
} else { } else {
rightValueListNode = right.asValueListNode(); rightValueListNode = right.asValueListNode();
} }
ValueNode.ValueListNode leftValueListNode; ValueListNode leftValueListNode;
if(left.isJsonNode()){ if(left.isJsonNode()){
ValueNode vn = left.asJsonNode().asValueListNode(ctx); ValueNode vn = left.asJsonNode().asValueListNode(ctx);
if(vn.isUndefinedNode()){ if(vn.isUndefinedNode()){

19
json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java

@ -4,6 +4,7 @@ import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.InvalidPathException; import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.Predicate; import com.jayway.jsonpath.Predicate;
import com.jayway.jsonpath.internal.CharacterIndex; import com.jayway.jsonpath.internal.CharacterIndex;
import static com.jayway.jsonpath.internal.filter.ValueNodes.*;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -197,10 +198,10 @@ public class FilterCompiler {
filter.setPosition(savepoint); filter.setPosition(savepoint);
} }
ValueNode.PathNode pathNode = left.asPathNode(); PathNode pathNode = left.asPathNode();
left = pathNode.asExistsCheck(pathNode.shouldExists()); left = pathNode.asExistsCheck(pathNode.shouldExists());
RelationalOperator operator = RelationalOperator.EXISTS; RelationalOperator operator = RelationalOperator.EXISTS;
ValueNode right = left.asPathNode().shouldExists() ? ValueNode.TRUE : ValueNode.FALSE; ValueNode right = left.asPathNode().shouldExists() ? ValueNodes.TRUE : ValueNodes.FALSE;
return new RelationalExpressionNode(left, operator, right); return new RelationalExpressionNode(left, operator, right);
} }
@ -239,7 +240,7 @@ public class FilterCompiler {
return RelationalOperator.fromString(operator.toString()); return RelationalOperator.fromString(operator.toString());
} }
private ValueNode.NullNode readNullLiteral() { private NullNode readNullLiteral() {
int begin = filter.position(); int begin = filter.position();
if(filter.currentChar() == NULL && filter.inBounds(filter.position() + 3)){ if(filter.currentChar() == NULL && filter.inBounds(filter.position() + 3)){
CharSequence nullValue = filter.subSequence(filter.position(), filter.position() + 4); CharSequence nullValue = filter.subSequence(filter.position(), filter.position() + 4);
@ -252,7 +253,7 @@ public class FilterCompiler {
throw new InvalidPathException("Expected <null> value"); throw new InvalidPathException("Expected <null> value");
} }
private ValueNode.JsonNode readJsonLiteral(){ private JsonNode readJsonLiteral(){
int begin = filter.position(); int begin = filter.position();
char openChar = filter.currentChar(); char openChar = filter.currentChar();
@ -273,7 +274,7 @@ public class FilterCompiler {
} }
private ValueNode.PatternNode readPattern() { private PatternNode readPattern() {
int begin = filter.position(); int begin = filter.position();
int closingIndex = filter.nextIndexOfUnescaped(PATTERN); int closingIndex = filter.nextIndexOfUnescaped(PATTERN);
if (closingIndex == -1) { if (closingIndex == -1) {
@ -289,7 +290,7 @@ public class FilterCompiler {
return ValueNode.createPatternNode(pattern); return ValueNode.createPatternNode(pattern);
} }
private ValueNode.StringNode readStringLiteral(char endChar) { private StringNode readStringLiteral(char endChar) {
int begin = filter.position(); int begin = filter.position();
int closingSingleQuoteIndex = filter.nextIndexOfUnescaped(endChar); int closingSingleQuoteIndex = filter.nextIndexOfUnescaped(endChar);
@ -303,7 +304,7 @@ public class FilterCompiler {
return ValueNode.createStringNode(stringLiteral, true); return ValueNode.createStringNode(stringLiteral, true);
} }
private ValueNode.NumberNode readNumberLiteral() { private NumberNode readNumberLiteral() {
int begin = filter.position(); int begin = filter.position();
while (filter.inBounds() && filter.isNumberCharacter(filter.position())) { while (filter.inBounds() && filter.isNumberCharacter(filter.position())) {
@ -314,7 +315,7 @@ public class FilterCompiler {
return ValueNode.createNumberNode(numberLiteral); return ValueNode.createNumberNode(numberLiteral);
} }
private ValueNode.BooleanNode readBooleanLiteral() { private BooleanNode readBooleanLiteral() {
int begin = filter.position(); int begin = filter.position();
int end = filter.currentChar() == TRUE ? filter.position() + 3 : filter.position() + 4; int end = filter.currentChar() == TRUE ? filter.position() + 3 : filter.position() + 4;
@ -331,7 +332,7 @@ public class FilterCompiler {
return ValueNode.createBooleanNode(boolValue); return ValueNode.createBooleanNode(boolValue);
} }
private ValueNode.PathNode readPath() { private PathNode readPath() {
char previousSignificantChar = filter.previousSignificantChar(); char previousSignificantChar = filter.previousSignificantChar();
int begin = filter.position(); int begin = filter.position();

653
json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java

@ -1,40 +1,17 @@
package com.jayway.jsonpath.internal.filter; package com.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration; import java.util.regex.Pattern;
import com.jayway.jsonpath.InvalidPathException; import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.JsonPathException; import com.jayway.jsonpath.JsonPathException;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.Predicate; import com.jayway.jsonpath.Predicate;
import com.jayway.jsonpath.internal.Path; import com.jayway.jsonpath.internal.Path;
import com.jayway.jsonpath.internal.Utils;
import com.jayway.jsonpath.internal.path.PathCompiler; import com.jayway.jsonpath.internal.path.PathCompiler;
import com.jayway.jsonpath.internal.path.PredicateContextImpl;
import com.jayway.jsonpath.spi.json.JsonProvider;
import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.JSONParser;
import net.minidev.json.parser.ParseException; import static com.jayway.jsonpath.internal.filter.ValueNodes.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
public abstract class ValueNode { public abstract class ValueNode {
public static final NullNode NULL_NODE = new NullNode();
public static final BooleanNode TRUE = new BooleanNode("true");
public static final BooleanNode FALSE = new BooleanNode("false");
public static final UndefinedNode UNDEFINED = new UndefinedNode();
public abstract Class<?> type(Predicate.PredicateContext ctx); public abstract Class<?> type(Predicate.PredicateContext ctx);
public boolean isPatternNode() { public boolean isPatternNode() {
@ -174,7 +151,7 @@ public abstract class ValueNode {
// //
//---------------------------------------------------- //----------------------------------------------------
public static ValueNode toValueNode(Object o){ public static ValueNode toValueNode(Object o){
if(o == null) return ValueNode.NULL_NODE; if(o == null) return NULL_NODE;
if(o instanceof ValueNode) return (ValueNode)o; if(o instanceof ValueNode) return (ValueNode)o;
if(o instanceof Class) return createClassNode((Class)o); if(o instanceof Class) return createClassNode((Class)o);
else if(isPath(o)) return new PathNode(o.toString(), false, false); else if(isPath(o)) return new PathNode(o.toString(), false, false);
@ -235,625 +212,5 @@ public abstract class ValueNode {
return new PathNode(path); return new PathNode(path);
} }
//----------------------------------------------------
//
// ValueNode Implementations
//
//----------------------------------------------------
public static class PatternNode extends ValueNode {
private final String pattern;
private final Pattern compiledPattern;
private PatternNode(CharSequence charSequence) {
String tmp = charSequence.toString();
int begin = tmp.indexOf('/');
int end = tmp.lastIndexOf('/');
int flags = tmp.endsWith("/i") ? Pattern.CASE_INSENSITIVE : 0;
this.pattern = tmp.substring(begin + 1, end);
this.compiledPattern = Pattern.compile(pattern, flags);
}
public PatternNode(Pattern pattern) {
this.pattern = pattern.pattern();
this.compiledPattern = pattern;
}
public Pattern getCompiledPattern() {
return compiledPattern;
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Void.TYPE;
}
public boolean isPatternNode() {
return true;
}
public PatternNode asPatternNode() {
return this;
}
@Override
public String toString() {
String flags = "";
if((compiledPattern.flags() & Pattern.CASE_INSENSITIVE) == Pattern.CASE_INSENSITIVE){
flags = "i";
}
if(!pattern.startsWith("/")){
return "/" + pattern + "/" + flags;
} else {
return pattern;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PatternNode)) return false;
PatternNode that = (PatternNode) o;
return !(compiledPattern != null ? !compiledPattern.equals(that.compiledPattern) : that.compiledPattern != null);
}
}
public static class JsonNode extends ValueNode {
private final Object json;
private final boolean parsed;
private JsonNode(CharSequence charSequence) {
json = charSequence.toString();
parsed = false;
}
public JsonNode(Object parsedJson) {
json = parsedJson;
parsed = true;
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
if(isArray(ctx)) return List.class;
else if(isMap(ctx)) return Map.class;
else if(parse(ctx) instanceof Number) return Number.class;
else if(parse(ctx) instanceof String) return String.class;
else if(parse(ctx) instanceof Boolean) return Boolean.class;
else return Void.class;
}
public boolean isJsonNode() {
return true;
}
public JsonNode asJsonNode() {
return this;
}
public ValueNode asValueListNode(Predicate.PredicateContext ctx){
if(!isArray(ctx)){
return UNDEFINED;
} else {
return new ValueListNode(Collections.unmodifiableList((List) parse(ctx)));
}
}
public Object parse(Predicate.PredicateContext ctx){
try {
return parsed ? json : new JSONParser(JSONParser.MODE_PERMISSIVE).parse(json.toString());
} catch (ParseException e) {
throw new IllegalArgumentException(e);
}
}
public boolean isParsed() {
return parsed;
}
public Object getJson() {
return json;
}
public boolean isArray(Predicate.PredicateContext ctx) {
return parse(ctx) instanceof List;
}
public boolean isMap(Predicate.PredicateContext ctx) {
return parse(ctx) instanceof Map;
}
public int length(Predicate.PredicateContext ctx) {
return isArray(ctx) ? ((List<?>) parse(ctx)).size() : -1;
}
public boolean isEmpty(Predicate.PredicateContext ctx) {
if (isArray(ctx) || isMap(ctx)) return ((Collection<?>) parse(ctx)).size() == 0;
else if((parse(ctx) instanceof String)) return ((String)parse(ctx)).length() == 0;
return true;
}
@Override
public String toString() {
return json.toString();
}
public boolean equals(JsonNode jsonNode, Predicate.PredicateContext ctx) {
if (this == jsonNode) return true;
return !(json != null ? !json.equals(jsonNode.parse(ctx)) : jsonNode.json != null);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof JsonNode)) return false;
JsonNode jsonNode = (JsonNode) o;
return !(json != null ? !json.equals(jsonNode.json) : jsonNode.json != null);
}
}
public static class StringNode extends ValueNode {
private final String string;
private boolean useSingleQuote = true;
private StringNode(CharSequence charSequence, boolean escape) {
if (escape && charSequence.length() > 1) {
char open = charSequence.charAt(0);
char close = charSequence.charAt(charSequence.length()-1);
if (open == '\'' && close == '\'') {
charSequence = charSequence.subSequence(1, charSequence.length()-1);
} else if (open == '"' && close == '"') {
charSequence = charSequence.subSequence(1, charSequence.length()-1);
useSingleQuote = false;
}
string = Utils.unescape(charSequence.toString());
} else {
string = charSequence.toString();
}
}
@Override
public NumberNode asNumberNode() {
BigDecimal number = null;
try {
number = new BigDecimal(string);
} catch (NumberFormatException nfe){
return NumberNode.NAN;
}
return new NumberNode(number);
}
public String getString() {
return string;
}
public int length(){
return getString().length();
}
public boolean isEmpty(){
return getString().isEmpty();
}
public boolean contains(String str) {
return getString().contains(str);
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return String.class;
}
public boolean isStringNode() {
return true;
}
public StringNode asStringNode() {
return this;
}
@Override
public String toString() {
String quote = useSingleQuote ? "'" : "\"";
return quote + Utils.escape(string, true) + quote;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof StringNode) && !(o instanceof NumberNode)) return false;
StringNode that = ((ValueNode) o).asStringNode();
return !(string != null ? !string.equals(that.getString()) : that.getString() != null);
}
}
public static class NumberNode extends ValueNode {
public static NumberNode NAN = new NumberNode((BigDecimal)null);
private final BigDecimal number;
private NumberNode(BigDecimal number) {
this.number = number;
}
private NumberNode(CharSequence num) {
number = new BigDecimal(num.toString());
}
@Override
public StringNode asStringNode() {
return new StringNode(number.toString(), false);
}
public BigDecimal getNumber() {
return number;
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Number.class;
}
public boolean isNumberNode() {
return true;
}
public NumberNode asNumberNode() {
return this;
}
@Override
public String toString() {
return number.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof NumberNode) && !(o instanceof StringNode)) return false;
NumberNode that = ((ValueNode)o).asNumberNode();
if(that == NumberNode.NAN){
return false;
} else {
return number.compareTo(that.number) == 0;
}
}
}
public static class BooleanNode extends ValueNode {
private final Boolean value;
private BooleanNode(CharSequence boolValue) {
value = Boolean.parseBoolean(boolValue.toString());
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Boolean.class;
}
public boolean isBooleanNode() {
return true;
}
public BooleanNode asBooleanNode() {
return this;
}
public boolean getBoolean() {
return value;
}
@Override
public String toString() {
return value.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BooleanNode)) return false;
BooleanNode that = (BooleanNode) o;
return !(value != null ? !value.equals(that.value) : that.value != null);
}
}
public static class ClassNode extends ValueNode {
private final Class clazz;
private ClassNode(Class clazz) {
this.clazz = clazz;
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Class.class;
}
public boolean isClassNode() {
return true;
}
public ClassNode asClassNode() {
return this;
}
public Class getClazz() {
return clazz;
}
@Override
public String toString() {
return clazz.getName();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ClassNode)) return false;
ClassNode that = (ClassNode) o;
return !(clazz != null ? !clazz.equals(that.clazz) : that.clazz != null);
}
}
public static class NullNode extends ValueNode {
private NullNode() {}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Void.class;
}
@Override
public boolean isNullNode() {
return true;
}
@Override
public NullNode asNullNode() {
return this;
}
@Override
public String toString() {
return "null";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof NullNode)) return false;
return true;
}
}
public static class UndefinedNode extends ValueNode {
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Void.class;
}
public UndefinedNode asUndefinedNode() {
return this;
}
public boolean isUndefinedNode() {
return true;
}
@Override
public boolean equals(Object o) {
return false;
}
}
public static class PredicateNode extends ValueNode {
private final Predicate predicate;
public PredicateNode(Predicate predicate) {
this.predicate = predicate;
}
public Predicate getPredicate() {
return predicate;
}
public PredicateNode asPredicateNode() {
return this;
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Void.class;
}
public boolean isPredicateNode() {
return true;
}
@Override
public boolean equals(Object o) {
return false;
}
@Override
public String toString() {
return predicate.toString();
}
}
public static class ValueListNode extends ValueNode implements Iterable<ValueNode> {
private List<ValueNode> nodes = new ArrayList<ValueNode>();
public ValueListNode(Collection<?> values) {
for (Object value : values) {
nodes.add(toValueNode(value));
}
}
public boolean contains(ValueNode node){
return nodes.contains(node);
}
public boolean subsetof(ValueListNode right) {
for (ValueNode leftNode : nodes) {
if (!right.nodes.contains(leftNode)) {
return false;
}
}
return true;
}
public List<ValueNode> getNodes() {
return Collections.unmodifiableList(nodes);
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return List.class;
}
public boolean isValueListNode() {
return true;
}
public ValueListNode asValueListNode() {
return this;
}
@Override
public String toString() {
return "[" + Utils.join(",", nodes) + "]";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ValueListNode)) return false;
ValueListNode that = (ValueListNode) o;
return !(that != null ? !nodes.equals(that.nodes) : that.nodes != null);
}
@Override
public Iterator<ValueNode> iterator() {
return nodes.iterator();
}
}
public static class PathNode extends ValueNode {
private static final Logger logger = LoggerFactory.getLogger(PathNode.class);
private final Path path;
private final boolean existsCheck;
private final boolean shouldExist;
PathNode(Path path) {
this(path, false, false);
}
PathNode(CharSequence charSequence, boolean existsCheck, boolean shouldExist) {
this(PathCompiler.compile(charSequence.toString()), existsCheck, shouldExist);
}
PathNode(Path path, boolean existsCheck, boolean shouldExist) {
this.path = path;
this.existsCheck = existsCheck;
this.shouldExist = shouldExist;
logger.trace("PathNode {} existsCheck: {}", path, existsCheck);
}
public Path getPath() {
return path;
}
public boolean isExistsCheck() {
return existsCheck;
}
public boolean shouldExists() {
return shouldExist;
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Void.class;
}
public boolean isPathNode() {
return true;
}
public PathNode asPathNode() {
return this;
}
public PathNode asExistsCheck(boolean shouldExist) {
return new PathNode(path, true, shouldExist);
}
@Override
public String toString() {
return existsCheck && ! shouldExist ? Utils.concat("!" , path.toString()) : path.toString();
}
public ValueNode evaluate(Predicate.PredicateContext ctx) {
if (isExistsCheck()) {
try {
Configuration c = Configuration.builder().jsonProvider(ctx.configuration().jsonProvider()).options(Option.REQUIRE_PROPERTIES).build();
Object result = path.evaluate(ctx.item(), ctx.root(), c).getValue(false);
return result == JsonProvider.UNDEFINED ? ValueNode.FALSE : ValueNode.TRUE;
} catch (PathNotFoundException e) {
return ValueNode.FALSE;
}
} else {
try {
Object res;
if (ctx instanceof PredicateContextImpl) {
//This will use cache for document ($) queries
PredicateContextImpl ctxi = (PredicateContextImpl) ctx;
res = ctxi.evaluate(path);
} else {
Object doc = path.isRootPath() ? ctx.root() : ctx.item();
res = path.evaluate(doc, ctx.root(), ctx.configuration()).getValue();
}
res = ctx.configuration().jsonProvider().unwrap(res);
if (res instanceof Number) return ValueNode.createNumberNode(res.toString());
else if (res instanceof BigDecimal) return ValueNode.createNumberNode(res.toString());
else if (res instanceof String) return ValueNode.createStringNode(res.toString(), false);
else if (res instanceof Boolean) return ValueNode.createBooleanNode(res.toString());
else if (res == null) return ValueNode.NULL_NODE;
else if (ctx.configuration().jsonProvider().isArray(res)) return ValueNode.createJsonNode(ctx.configuration().mappingProvider().map(res, List.class, ctx.configuration()));
else if (ctx.configuration().jsonProvider().isMap(res)) return ValueNode.createJsonNode(ctx.configuration().mappingProvider().map(res, Map.class, ctx.configuration()));
else throw new JsonPathException("Could not convert " + res.toString() + " to a ValueNode");
} catch (PathNotFoundException e) {
return ValueNode.UNDEFINED;
}
}
}
}
} }

662
json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java

@ -0,0 +1,662 @@
package com.jayway.jsonpath.internal.filter;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
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.internal.Path;
import com.jayway.jsonpath.internal.Utils;
import com.jayway.jsonpath.internal.path.PathCompiler;
import com.jayway.jsonpath.internal.path.PredicateContextImpl;
import com.jayway.jsonpath.spi.json.JsonProvider;
import net.minidev.json.parser.JSONParser;
import net.minidev.json.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Moved these nodes out of the ValueNode abstract class.
* This is to avoid this possible issue:
*
* Classes that refer to their own subclasses in their static initializers or in static fields.
* Such references can cause JVM-level deadlocks in multithreaded environment, when
* one thread tries to load superclass and another thread tries to load subclass at the same time.
*/
public interface ValueNodes {
NullNode NULL_NODE = new NullNode();
BooleanNode TRUE = new BooleanNode("true");
BooleanNode FALSE = new BooleanNode("false");
UndefinedNode UNDEFINED = new UndefinedNode();
//----------------------------------------------------
//
// ValueNode Implementations
//
//----------------------------------------------------
class PatternNode extends ValueNode {
private final String pattern;
private final Pattern compiledPattern;
PatternNode(CharSequence charSequence) {
String tmp = charSequence.toString();
int begin = tmp.indexOf('/');
int end = tmp.lastIndexOf('/');
int flags = tmp.endsWith("/i") ? Pattern.CASE_INSENSITIVE : 0;
this.pattern = tmp.substring(begin + 1, end);
this.compiledPattern = Pattern.compile(pattern, flags);
}
PatternNode(Pattern pattern) {
this.pattern = pattern.pattern();
this.compiledPattern = pattern;
}
Pattern getCompiledPattern() {
return compiledPattern;
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Void.TYPE;
}
public boolean isPatternNode() {
return true;
}
public PatternNode asPatternNode() {
return this;
}
@Override
public String toString() {
String flags = "";
if((compiledPattern.flags() & Pattern.CASE_INSENSITIVE) == Pattern.CASE_INSENSITIVE){
flags = "i";
}
if(!pattern.startsWith("/")){
return "/" + pattern + "/" + flags;
} else {
return pattern;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PatternNode)) return false;
PatternNode that = (PatternNode) o;
return !(compiledPattern != null ? !compiledPattern.equals(that.compiledPattern) : that.compiledPattern != null);
}
}
class JsonNode extends ValueNode {
private final Object json;
private final boolean parsed;
JsonNode(CharSequence charSequence) {
json = charSequence.toString();
parsed = false;
}
JsonNode(Object parsedJson) {
json = parsedJson;
parsed = true;
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
if(isArray(ctx)) return List.class;
else if(isMap(ctx)) return Map.class;
else if(parse(ctx) instanceof Number) return Number.class;
else if(parse(ctx) instanceof String) return String.class;
else if(parse(ctx) instanceof Boolean) return Boolean.class;
else return Void.class;
}
public boolean isJsonNode() {
return true;
}
public JsonNode asJsonNode() {
return this;
}
public ValueNode asValueListNode(Predicate.PredicateContext ctx){
if(!isArray(ctx)){
return UNDEFINED;
} else {
return new ValueListNode(Collections.unmodifiableList((List) parse(ctx)));
}
}
public Object parse(Predicate.PredicateContext ctx){
try {
return parsed ? json : new JSONParser(JSONParser.MODE_PERMISSIVE).parse(json.toString());
} catch (ParseException e) {
throw new IllegalArgumentException(e);
}
}
public boolean isParsed() {
return parsed;
}
public Object getJson() {
return json;
}
public boolean isArray(Predicate.PredicateContext ctx) {
return parse(ctx) instanceof List;
}
public boolean isMap(Predicate.PredicateContext ctx) {
return parse(ctx) instanceof Map;
}
public int length(Predicate.PredicateContext ctx) {
return isArray(ctx) ? ((List<?>) parse(ctx)).size() : -1;
}
public boolean isEmpty(Predicate.PredicateContext ctx) {
if (isArray(ctx) || isMap(ctx)) return ((Collection<?>) parse(ctx)).size() == 0;
else if((parse(ctx) instanceof String)) return ((String)parse(ctx)).length() == 0;
return true;
}
@Override
public String toString() {
return json.toString();
}
public boolean equals(JsonNode jsonNode, Predicate.PredicateContext ctx) {
if (this == jsonNode) return true;
return !(json != null ? !json.equals(jsonNode.parse(ctx)) : jsonNode.json != null);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof JsonNode)) return false;
JsonNode jsonNode = (JsonNode) o;
return !(json != null ? !json.equals(jsonNode.json) : jsonNode.json != null);
}
}
class StringNode extends ValueNode {
private final String string;
private boolean useSingleQuote = true;
StringNode(CharSequence charSequence, boolean escape) {
if (escape && charSequence.length() > 1) {
char open = charSequence.charAt(0);
char close = charSequence.charAt(charSequence.length()-1);
if (open == '\'' && close == '\'') {
charSequence = charSequence.subSequence(1, charSequence.length()-1);
} else if (open == '"' && close == '"') {
charSequence = charSequence.subSequence(1, charSequence.length()-1);
useSingleQuote = false;
}
string = Utils.unescape(charSequence.toString());
} else {
string = charSequence.toString();
}
}
@Override
public NumberNode asNumberNode() {
BigDecimal number = null;
try {
number = new BigDecimal(string);
} catch (NumberFormatException nfe){
return NumberNode.NAN;
}
return new NumberNode(number);
}
public String getString() {
return string;
}
public int length(){
return getString().length();
}
public boolean isEmpty(){
return getString().isEmpty();
}
public boolean contains(String str) {
return getString().contains(str);
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return String.class;
}
public boolean isStringNode() {
return true;
}
public StringNode asStringNode() {
return this;
}
@Override
public String toString() {
String quote = useSingleQuote ? "'" : "\"";
return quote + Utils.escape(string, true) + quote;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof StringNode) && !(o instanceof NumberNode)) return false;
StringNode that = ((ValueNode) o).asStringNode();
return !(string != null ? !string.equals(that.getString()) : that.getString() != null);
}
}
class NumberNode extends ValueNode {
public static NumberNode NAN = new NumberNode((BigDecimal)null);
private final BigDecimal number;
NumberNode(BigDecimal number) {
this.number = number;
}
NumberNode(CharSequence num) {
number = new BigDecimal(num.toString());
}
@Override
public StringNode asStringNode() {
return new StringNode(number.toString(), false);
}
public BigDecimal getNumber() {
return number;
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Number.class;
}
public boolean isNumberNode() {
return true;
}
public NumberNode asNumberNode() {
return this;
}
@Override
public String toString() {
return number.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof NumberNode) && !(o instanceof StringNode)) return false;
NumberNode that = ((ValueNode)o).asNumberNode();
if(that == NumberNode.NAN){
return false;
} else {
return number.compareTo(that.number) == 0;
}
}
}
class BooleanNode extends ValueNode {
private final Boolean value;
private BooleanNode(CharSequence boolValue) {
value = Boolean.parseBoolean(boolValue.toString());
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Boolean.class;
}
public boolean isBooleanNode() {
return true;
}
public BooleanNode asBooleanNode() {
return this;
}
public boolean getBoolean() {
return value;
}
@Override
public String toString() {
return value.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BooleanNode)) return false;
BooleanNode that = (BooleanNode) o;
return !(value != null ? !value.equals(that.value) : that.value != null);
}
}
class ClassNode extends ValueNode {
private final Class clazz;
ClassNode(Class clazz) {
this.clazz = clazz;
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Class.class;
}
public boolean isClassNode() {
return true;
}
public ClassNode asClassNode() {
return this;
}
public Class getClazz() {
return clazz;
}
@Override
public String toString() {
return clazz.getName();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ClassNode)) return false;
ClassNode that = (ClassNode) o;
return !(clazz != null ? !clazz.equals(that.clazz) : that.clazz != null);
}
}
class NullNode extends ValueNode {
private NullNode() {}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Void.class;
}
@Override
public boolean isNullNode() {
return true;
}
@Override
public NullNode asNullNode() {
return this;
}
@Override
public String toString() {
return "null";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof NullNode)) return false;
return true;
}
}
class UndefinedNode extends ValueNode {
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Void.class;
}
public UndefinedNode asUndefinedNode() {
return this;
}
public boolean isUndefinedNode() {
return true;
}
@Override
public boolean equals(Object o) {
return false;
}
}
class PredicateNode extends ValueNode {
private final Predicate predicate;
public PredicateNode(Predicate predicate) {
this.predicate = predicate;
}
public Predicate getPredicate() {
return predicate;
}
public PredicateNode asPredicateNode() {
return this;
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Void.class;
}
public boolean isPredicateNode() {
return true;
}
@Override
public boolean equals(Object o) {
return false;
}
@Override
public String toString() {
return predicate.toString();
}
}
class ValueListNode extends ValueNode implements Iterable<ValueNode> {
private List<ValueNode> nodes = new ArrayList<ValueNode>();
public ValueListNode(Collection<?> values) {
for (Object value : values) {
nodes.add(toValueNode(value));
}
}
public boolean contains(ValueNode node){
return nodes.contains(node);
}
public boolean subsetof(ValueListNode right) {
for (ValueNode leftNode : nodes) {
if (!right.nodes.contains(leftNode)) {
return false;
}
}
return true;
}
public List<ValueNode> getNodes() {
return Collections.unmodifiableList(nodes);
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return List.class;
}
public boolean isValueListNode() {
return true;
}
public ValueListNode asValueListNode() {
return this;
}
@Override
public String toString() {
return "[" + Utils.join(",", nodes) + "]";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ValueListNode)) return false;
ValueListNode that = (ValueListNode) o;
return nodes.equals(that.nodes);
}
@Override
public Iterator<ValueNode> iterator() {
return nodes.iterator();
}
}
class PathNode extends ValueNode {
private static final Logger logger = LoggerFactory.getLogger(PathNode.class);
private final Path path;
private final boolean existsCheck;
private final boolean shouldExist;
PathNode(Path path) {
this(path, false, false);
}
PathNode(CharSequence charSequence, boolean existsCheck, boolean shouldExist) {
this(PathCompiler.compile(charSequence.toString()), existsCheck, shouldExist);
}
PathNode(Path path, boolean existsCheck, boolean shouldExist) {
this.path = path;
this.existsCheck = existsCheck;
this.shouldExist = shouldExist;
logger.trace("PathNode {} existsCheck: {}", path, existsCheck);
}
public Path getPath() {
return path;
}
public boolean isExistsCheck() {
return existsCheck;
}
public boolean shouldExists() {
return shouldExist;
}
@Override
public Class<?> type(Predicate.PredicateContext ctx) {
return Void.class;
}
public boolean isPathNode() {
return true;
}
public PathNode asPathNode() {
return this;
}
public PathNode asExistsCheck(boolean shouldExist) {
return new PathNode(path, true, shouldExist);
}
@Override
public String toString() {
return existsCheck && ! shouldExist ? Utils.concat("!" , path.toString()) : path.toString();
}
public ValueNode evaluate(Predicate.PredicateContext ctx) {
if (isExistsCheck()) {
try {
Configuration c = Configuration.builder().jsonProvider(ctx.configuration().jsonProvider()).options(Option.REQUIRE_PROPERTIES).build();
Object result = path.evaluate(ctx.item(), ctx.root(), c).getValue(false);
return result == JsonProvider.UNDEFINED ? FALSE : TRUE;
} catch (PathNotFoundException e) {
return FALSE;
}
} else {
try {
Object res;
if (ctx instanceof PredicateContextImpl) {
//This will use cache for document ($) queries
PredicateContextImpl ctxi = (PredicateContextImpl) ctx;
res = ctxi.evaluate(path);
} else {
Object doc = path.isRootPath() ? ctx.root() : ctx.item();
res = path.evaluate(doc, ctx.root(), ctx.configuration()).getValue();
}
res = ctx.configuration().jsonProvider().unwrap(res);
if (res instanceof Number) return ValueNode.createNumberNode(res.toString());
else if (res instanceof String) return ValueNode.createStringNode(res.toString(), false);
else if (res instanceof Boolean) return ValueNode.createBooleanNode(res.toString());
else if (res == null) return NULL_NODE;
else if (ctx.configuration().jsonProvider().isArray(res)) return ValueNode.createJsonNode(ctx.configuration().mappingProvider().map(res, List.class, ctx.configuration()));
else if (ctx.configuration().jsonProvider().isMap(res)) return ValueNode.createJsonNode(ctx.configuration().mappingProvider().map(res, Map.class, ctx.configuration()));
else throw new JsonPathException("Could not convert " + res.toString() + " to a ValueNode");
} catch (PathNotFoundException e) {
return UNDEFINED;
}
}
}
}
}

2
json-path/src/main/java/com/jayway/jsonpath/internal/function/text/Concatenate.java

@ -15,7 +15,7 @@ import java.util.List;
public class Concatenate implements PathFunction { public class Concatenate implements PathFunction {
@Override @Override
public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) { public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {
StringBuffer result = new StringBuffer(); StringBuilder result = new StringBuilder();
if(ctx.configuration().jsonProvider().isArray(model)){ if(ctx.configuration().jsonProvider().isArray(model)){
Iterable<?> objects = ctx.configuration().jsonProvider().toIterable(model); Iterable<?> objects = ctx.configuration().jsonProvider().toIterable(model);
for (Object obj : objects) { for (Object obj : objects) {

52
json-path/src/main/java/com/jayway/jsonpath/internal/path/ArrayIndexToken.java

@ -0,0 +1,52 @@
/*
* Copyright 2011 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jayway.jsonpath.internal.path;
import com.jayway.jsonpath.internal.PathRef;
import static java.lang.String.format;
public class ArrayIndexToken extends ArrayPathToken {
private final ArrayIndexOperation arrayIndexOperation;
ArrayIndexToken(final ArrayIndexOperation arrayIndexOperation) {
this.arrayIndexOperation = arrayIndexOperation;
}
@Override
public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
if (!checkArrayModel(currentPath, model, ctx))
return;
if (arrayIndexOperation.isSingleIndexOperation()) {
handleArrayIndex(arrayIndexOperation.indexes().get(0), currentPath, model, ctx);
} else {
for (Integer index : arrayIndexOperation.indexes()) {
handleArrayIndex(index, currentPath, model, ctx);
}
}
}
@Override
public String getPathFragment() {
return arrayIndexOperation.toString();
}
@Override
public boolean isTokenDefinite() {
return arrayIndexOperation.isSingleIndexOperation();
}
}

138
json-path/src/main/java/com/jayway/jsonpath/internal/path/ArrayPathToken.java

@ -22,143 +22,7 @@ import org.slf4j.LoggerFactory;
import static java.lang.String.format; import static java.lang.String.format;
/** public abstract class ArrayPathToken extends PathToken {
*
*/
public class ArrayPathToken extends PathToken {
private static final Logger logger = LoggerFactory.getLogger(ArrayPathToken.class);
private final ArraySliceOperation arraySliceOperation;
private final ArrayIndexOperation arrayIndexOperation;
ArrayPathToken(final ArraySliceOperation arraySliceOperation) {
this.arraySliceOperation = arraySliceOperation;
this.arrayIndexOperation = null;
}
ArrayPathToken(final ArrayIndexOperation arrayIndexOperation) {
this.arrayIndexOperation = arrayIndexOperation;
this.arraySliceOperation = null;
}
@Override
public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
if (! checkArrayModel(currentPath, model, ctx))
return;
if(arraySliceOperation != null){
evaluateSliceOperation(currentPath, parent, model, ctx);
} else {
evaluateIndexOperation(currentPath, parent, model, ctx);
}
}
public void evaluateIndexOperation(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
if (! checkArrayModel(currentPath, model, ctx))
return;
if(arrayIndexOperation.isSingleIndexOperation()){
handleArrayIndex(arrayIndexOperation.indexes().get(0), currentPath, model, ctx);
} else {
for (Integer index : arrayIndexOperation.indexes()) {
handleArrayIndex(index, currentPath, model, ctx);
}
}
}
public void evaluateSliceOperation(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
if (! checkArrayModel(currentPath, model, ctx))
return;
switch (arraySliceOperation.operation()) {
case SLICE_FROM:
sliceFrom(arraySliceOperation, currentPath, parent, model, ctx);
break;
case SLICE_BETWEEN:
sliceBetween(arraySliceOperation, currentPath, parent, model, ctx);
break;
case SLICE_TO:
sliceTo(arraySliceOperation, currentPath, parent, model, ctx);
break;
}
}
public void sliceFrom(ArraySliceOperation operation, String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
int length = ctx.jsonProvider().length(model);
int from = operation.from();
if (from < 0) {
//calculate slice start from array length
from = length + from;
}
from = Math.max(0, from);
logger.debug("Slice from index on array with length: {}. From index: {} to: {}. Input: {}", length, from, length - 1, toString());
if (length == 0 || from >= length) {
return;
}
for (int i = from; i < length; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
}
public void sliceBetween(ArraySliceOperation operation, String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
int length = ctx.jsonProvider().length(model);
int from = operation.from();
int to = operation.to();
to = Math.min(length, to);
if (from >= to || length == 0) {
return;
}
logger.debug("Slice between indexes on array with length: {}. From index: {} to: {}. Input: {}", length, from, to, toString());
for (int i = from; i < to; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
}
public void sliceTo(ArraySliceOperation operation, String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
int length = ctx.jsonProvider().length(model);
if (length == 0) {
return;
}
int to = operation.to();
if (to < 0) {
//calculate slice end from array length
to = length + to;
}
to = Math.min(length, to);
logger.debug("Slice to index on array with length: {}. From index: 0 to: {}. Input: {}", length, to, toString());
for (int i = 0; i < to; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
}
@Override
public String getPathFragment() {
if(arrayIndexOperation != null){
return arrayIndexOperation.toString();
} else {
return arraySliceOperation.toString();
}
}
@Override
public boolean isTokenDefinite() {
if(arrayIndexOperation != null){
return arrayIndexOperation.isSingleIndexOperation();
} else {
return false;
}
}
/** /**
* Check if model is non-null and array. * Check if model is non-null and array.

18
json-path/src/main/java/com/jayway/jsonpath/internal/path/ArraySliceOperation.java

@ -58,19 +58,19 @@ public class ArraySliceOperation {
Integer tempFrom = tryRead(tokens, 0); Integer tempFrom = tryRead(tokens, 0);
Integer tempTo = tryRead(tokens, 1); Integer tempTo = tryRead(tokens, 1);
Operation tempOperpation; Operation tempOperation;
if(tempFrom != null && tempTo == null){ if (tempFrom != null && tempTo == null) {
tempOperpation = Operation.SLICE_FROM; tempOperation = Operation.SLICE_FROM;
} else if(tempFrom != null && tempTo != null){ } else if (tempFrom != null) {
tempOperpation = Operation.SLICE_BETWEEN; tempOperation = Operation.SLICE_BETWEEN;
} else if(tempFrom == null && tempTo != null){ } else if (tempTo != null) {
tempOperpation = Operation.SLICE_TO; tempOperation = Operation.SLICE_TO;
} else { } else {
throw new InvalidPathException("Failed to parse SliceOperation: " + operation); throw new InvalidPathException("Failed to parse SliceOperation: " + operation);
} }
return new ArraySliceOperation(tempFrom, tempTo, tempOperpation); return new ArraySliceOperation(tempFrom, tempTo, tempOperation);
} }
private static Integer tryRead(String[] tokens, int idx){ private static Integer tryRead(String[] tokens, int idx){

114
json-path/src/main/java/com/jayway/jsonpath/internal/path/ArraySliceToken.java

@ -0,0 +1,114 @@
/*
* Copyright 2011 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jayway.jsonpath.internal.path;
import com.jayway.jsonpath.internal.PathRef;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ArraySliceToken extends ArrayPathToken {
private static final Logger logger = LoggerFactory.getLogger(ArraySliceToken.class);
private final ArraySliceOperation operation;
ArraySliceToken(final ArraySliceOperation operation) {
this.operation = operation;
}
@Override
public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
if (!checkArrayModel(currentPath, model, ctx))
return;
switch (operation.operation()) {
case SLICE_FROM:
sliceFrom(currentPath, parent, model, ctx);
break;
case SLICE_BETWEEN:
sliceBetween(currentPath, parent, model, ctx);
break;
case SLICE_TO:
sliceTo(currentPath, parent, model, ctx);
break;
}
}
private void sliceFrom(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
int length = ctx.jsonProvider().length(model);
int from = operation.from();
if (from < 0) {
//calculate slice start from array length
from = length + from;
}
from = Math.max(0, from);
logger.debug("Slice from index on array with length: {}. From index: {} to: {}. Input: {}", length, from, length - 1, toString());
if (length == 0 || from >= length) {
return;
}
for (int i = from; i < length; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
}
private void sliceBetween(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
int length = ctx.jsonProvider().length(model);
int from = operation.from();
int to = operation.to();
to = Math.min(length, to);
if (from >= to || length == 0) {
return;
}
logger.debug("Slice between indexes on array with length: {}. From index: {} to: {}. Input: {}", length, from, to, toString());
for (int i = from; i < to; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
}
private void sliceTo(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
int length = ctx.jsonProvider().length(model);
if (length == 0) {
return;
}
int to = operation.to();
if (to < 0) {
//calculate slice end from array length
to = length + to;
}
to = Math.min(length, to);
logger.debug("Slice to index on array with length: {}. From index: 0 to: {}. Input: {}", length, to, toString());
for (int i = 0; i < to; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
}
@Override
public String getPathFragment() {
return operation.toString();
}
@Override
public boolean isTokenDefinite() {
return false;
}
}

2
json-path/src/main/java/com/jayway/jsonpath/internal/path/CompiledPath.java

@ -97,7 +97,7 @@ public class CompiledPath implements Path {
try { try {
PathRef op = ctx.forUpdate() ? PathRef.createRoot(rootDocument) : PathRef.NO_OP; PathRef op = ctx.forUpdate() ? PathRef.createRoot(rootDocument) : PathRef.NO_OP;
root.evaluate("", op, document, ctx); root.evaluate("", op, document, ctx);
} catch (EvaluationAbortException abort){}; } catch (EvaluationAbortException abort) {}
return ctx; return ctx;
} }

4
json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java

@ -275,7 +275,7 @@ public class PathCompiler {
Boolean endOfStream = false; Boolean endOfStream = false;
char priorChar = 0; char priorChar = 0;
List<Parameter> parameters = new ArrayList<Parameter>(); List<Parameter> parameters = new ArrayList<Parameter>();
StringBuffer parameter = new StringBuffer(); StringBuilder parameter = new StringBuilder();
while (path.inBounds() && !endOfStream) { while (path.inBounds() && !endOfStream) {
char c = path.currentChar(); char c = path.currentChar();
path.incrementPosition(1); path.incrementPosition(1);
@ -580,7 +580,7 @@ public class PathCompiler {
} }
break; break;
} else if (c == potentialStringDelimiter) { } else if (c == potentialStringDelimiter) {
if (inProperty && !inEscape) { if (inProperty) {
char nextSignificantChar = path.nextSignificantChar(readPosition); char nextSignificantChar = path.nextSignificantChar(readPosition);
if (nextSignificantChar != CLOSE_SQUARE_BRACKET && nextSignificantChar != COMMA) { if (nextSignificantChar != CLOSE_SQUARE_BRACKET && nextSignificantChar != COMMA) {
fail("Property must be separated by comma or Property must be terminated close square bracket at index "+readPosition); fail("Property must be separated by comma or Property must be terminated close square bracket at index "+readPosition);

4
json-path/src/main/java/com/jayway/jsonpath/internal/path/PathTokenFactory.java

@ -23,11 +23,11 @@ public class PathTokenFactory {
} }
public static PathToken createSliceArrayPathToken(final ArraySliceOperation arraySliceOperation) { public static PathToken createSliceArrayPathToken(final ArraySliceOperation arraySliceOperation) {
return new ArrayPathToken(arraySliceOperation); return new ArraySliceToken(arraySliceOperation);
} }
public static PathToken createIndexArrayPathToken(final ArrayIndexOperation arrayIndexOperation) { public static PathToken createIndexArrayPathToken(final ArrayIndexOperation arrayIndexOperation) {
return new ArrayPathToken(arrayIndexOperation); return new ArrayIndexToken(arrayIndexOperation);
} }
public static PathToken createWildCardPathToken() { public static PathToken createWildCardPathToken() {

3
json-path/src/main/java/com/jayway/jsonpath/internal/path/PredicatePathToken.java

@ -20,6 +20,7 @@ import com.jayway.jsonpath.Predicate;
import com.jayway.jsonpath.internal.PathRef; import com.jayway.jsonpath.internal.PathRef;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import static java.lang.String.format; import static java.lang.String.format;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
@ -33,7 +34,7 @@ public class PredicatePathToken extends PathToken {
private final Collection<Predicate> predicates; private final Collection<Predicate> predicates;
PredicatePathToken(Predicate filter) { PredicatePathToken(Predicate filter) {
this.predicates = asList(filter); this.predicates = Collections.singletonList(filter);
} }
PredicatePathToken(Collection<Predicate> predicates) { PredicatePathToken(Collection<Predicate> predicates) {

2
json-path/src/main/java/com/jayway/jsonpath/internal/path/RootPathToken.java

@ -27,7 +27,7 @@ public class RootPathToken extends PathToken {
RootPathToken(char rootToken) { RootPathToken(char rootToken) {
this.rootToken = Character.toString(rootToken);; this.rootToken = Character.toString(rootToken);
this.tail = this; this.tail = this;
this.tokenCount = 1; this.tokenCount = 1;
} }

4
json-path/src/main/java/com/jayway/jsonpath/internal/path/WildcardPathToken.java

@ -14,6 +14,8 @@
*/ */
package com.jayway.jsonpath.internal.path; package com.jayway.jsonpath.internal.path;
import java.util.Collections;
import com.jayway.jsonpath.Option; import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException; import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.internal.PathRef; import com.jayway.jsonpath.internal.PathRef;
@ -32,7 +34,7 @@ public class WildcardPathToken extends PathToken {
public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) { public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {
if (ctx.jsonProvider().isMap(model)) { if (ctx.jsonProvider().isMap(model)) {
for (String property : ctx.jsonProvider().getPropertyKeys(model)) { for (String property : ctx.jsonProvider().getPropertyKeys(model)) {
handleObjectProperty(currentPath, model, ctx, asList(property)); handleObjectProperty(currentPath, model, ctx, Collections.singletonList(property));
} }
} else if (ctx.jsonProvider().isArray(model)) { } else if (ctx.jsonProvider().isArray(model)) {
for (int idx = 0; idx < ctx.jsonProvider().length(model); idx++) { for (int idx = 0; idx < ctx.jsonProvider().length(model); idx++) {

2
json-path/src/main/java/com/jayway/jsonpath/spi/cache/CacheProvider.java vendored

@ -6,7 +6,6 @@ import static com.jayway.jsonpath.internal.Utils.notNull;
public class CacheProvider { public class CacheProvider {
private static Cache cache; private static Cache cache;
private static boolean cachingEnabled;
public static void setCache(Cache cache){ public static void setCache(Cache cache){
notNull(cache, "Cache may not be null"); notNull(cache, "Cache may not be null");
@ -16,7 +15,6 @@ public class CacheProvider {
} else { } else {
CacheProvider.cache = cache; CacheProvider.cache = cache;
} }
cachingEnabled = !(CacheProvider.cache instanceof NOOPCache);
} }
} }

2
json-path/src/main/java/com/jayway/jsonpath/spi/json/AbstractJsonProvider.java

@ -162,7 +162,7 @@ public abstract class AbstractJsonProvider implements JsonProvider {
* @return an Iterable that iterates over the entries of an array * @return an Iterable that iterates over the entries of an array
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Iterable<? extends Object> toIterable(Object obj) { public Iterable<?> toIterable(Object obj) {
if (isArray(obj)) if (isArray(obj))
return ((Iterable) obj); return ((Iterable) obj);
else else

3
json-path/src/test/java/com/jayway/jsonpath/FilterTest.java

@ -279,7 +279,8 @@ public class FilterTest extends BaseTest {
Filter farr = parse("[?(@.foo == " + arr + ")]"); Filter farr = parse("[?(@.foo == " + arr + ")]");
//Filter fobjF = parse("[?(@.foo == " + nest + ")]"); //Filter fobjF = parse("[?(@.foo == " + nest + ")]");
//Filter fobjT = parse("[?(@.bar == " + nest + ")]"); //Filter fobjT = parse("[?(@.bar == " + nest + ")]");
assertThat(farr.apply(context)).isEqualTo(true); boolean apply = farr.apply(context);
assertThat(apply).isEqualTo(true);
//assertThat(fobjF.apply(context)).isEqualTo(false); //assertThat(fobjF.apply(context)).isEqualTo(false);
//assertThat(fobjT.apply(context)).isEqualTo(true); //assertThat(fobjT.apply(context)).isEqualTo(true);
} }

Loading…
Cancel
Save