diff --git a/json-path/src/main/java/com/jayway/jsonpath/EvaluationCallback.java b/json-path/src/main/java/com/jayway/jsonpath/EvaluationCallback.java index 5e2db2e5..f5fe2a76 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/EvaluationCallback.java +++ b/json-path/src/main/java/com/jayway/jsonpath/EvaluationCallback.java @@ -26,12 +26,12 @@ public interface EvaluationCallback { * Callback invoked when result is found * @param path -- the specific path that was triggered */ - public void resultFound(Object source, Object obj, Path path) throws Exception; + public void resultFound(Path path) throws Exception; /** * Callback invoked when the parser leaves the region in which the match * was found * @param path -- the specific path that was untriggered */ - public void resultFoundExit(Object source, Object obj, Path path) throws Exception; + public void resultFoundExit(Path path) throws Exception; } diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/token/ArrayToken.java b/json-path/src/main/java/com/jayway/jsonpath/internal/token/ArrayToken.java index fc1ec1a5..3981147a 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/token/ArrayToken.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/token/ArrayToken.java @@ -5,7 +5,7 @@ package com.jayway.jsonpath.internal.token; * * @author Hunter Payne **/ -public class ArrayToken extends TokenStackElement +public class ArrayToken implements TokenStackElement { int currentIndex; TokenStackElement value; // can be an object, array, or property diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/token/FloatToken.java b/json-path/src/main/java/com/jayway/jsonpath/internal/token/FloatToken.java index 8015b8ad..561eb613 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/token/FloatToken.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/token/FloatToken.java @@ -5,7 +5,7 @@ package com.jayway.jsonpath.internal.token; * * @author Hunter Payne **/ -public class FloatToken extends TokenStackElement +public class FloatToken implements TokenStackElement { public float value; diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/token/IntToken.java b/json-path/src/main/java/com/jayway/jsonpath/internal/token/IntToken.java index e91b407f..df3dc314 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/token/IntToken.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/token/IntToken.java @@ -5,7 +5,7 @@ package com.jayway.jsonpath.internal.token; * * @author Hunter Payne **/ -public class IntToken extends TokenStackElement +public class IntToken implements TokenStackElement { public int value; diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/token/ObjectToken.java b/json-path/src/main/java/com/jayway/jsonpath/internal/token/ObjectToken.java index aacceca4..408580fd 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/token/ObjectToken.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/token/ObjectToken.java @@ -5,7 +5,7 @@ package com.jayway.jsonpath.internal.token; * * @author Hunter Payne **/ -public class ObjectToken extends TokenStackElement +public class ObjectToken implements TokenStackElement { String key; TokenStackElement value; // can be an array, object, or property diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/token/StringToken.java b/json-path/src/main/java/com/jayway/jsonpath/internal/token/StringToken.java index aef4eeb5..cbc5d334 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/token/StringToken.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/token/StringToken.java @@ -7,7 +7,7 @@ import java.util.regex.Pattern; * * @author Hunter Payne **/ -public class StringToken extends TokenStackElement +public class StringToken implements TokenStackElement { public String value; public Pattern pattern; diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/token/TokenStack.java b/json-path/src/main/java/com/jayway/jsonpath/internal/token/TokenStack.java index 0ef57ee3..ab55f7d2 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/token/TokenStack.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/token/TokenStack.java @@ -2,13 +2,14 @@ package com.jayway.jsonpath.internal.token; import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.EvaluationCallback; import com.jayway.jsonpath.internal.Path; import com.fasterxml.jackson.core.JsonParser; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.core.JsonToken; /** * @@ -16,18 +17,15 @@ import org.slf4j.LoggerFactory; **/ public class TokenStack { - private static final Logger log = LoggerFactory.getLogger(TokenStack.class); + protected static Logger log = Logger.getLogger("com.jayway.jsonpath"); protected Configuration conf; protected Stack elements; - protected Stack objStack; protected List paths; protected Map matchedPaths; private TokenStackElement curr; private Path rootMatch; - private Class jsonArrayType; - private Class jsonObjectType; public TokenStack(Configuration conf) { @@ -35,11 +33,7 @@ public class TokenStack paths = new ArrayList(); matchedPaths = new HashMap(); elements = new Stack(); - objStack = new Stack(); rootMatch = null; - - this.jsonArrayType = this.getNewJsonArray().getClass(); - this.jsonObjectType = this.getNewJsonObject().getClass(); } public Stack getStack() @@ -55,26 +49,28 @@ public class TokenStack paths.add(path); } - public void read(JsonParser parser, EvaluationCallback callback) - throws Exception - { - read(parser,callback,true); - } - /** - * reads from stream and notifies the callback of matched registered paths, with results. - * Note: GSON not supported + * reads from stream and notifies the callback of matched registered paths */ - public void read(JsonParser parser, EvaluationCallback callback, boolean getParents) + public void read(JsonParser parser, EvaluationCallback callback) throws Exception { assert(callback != null); - Object obj = null; boolean needsPathCheck = false; - + /* + if (null == curr && elements.empty()) { + // check for $ patterns + for (Path path : paths) { + if (path.checkForMatch(this)) { + matchedPaths.put(curr, path); + callback.resultFound(path); + rootMatch = path; + } + } + } + */ while (parser.nextToken() != null) { - //log.debug("type/name/val: " + parser.getCurrentToken() + " " + parser.getCurrentName() + " " + parser.getText()); boolean saveMatch = false; switch (parser.getCurrentToken()) { case START_ARRAY: @@ -89,42 +85,33 @@ public class TokenStack saveMatch = true; needsPathCheck = true; elements.push(curr); - - obj = stackPush(parser.getCurrentName(),getNewJsonArray()); break; } case END_ARRAY: { Path match = matchedPaths.remove(curr); if (match != null) { - callback.resultFoundExit(parser.getCurrentToken(), obj, match); + callback.resultFoundExit(match); } elements.pop(); if (elements.empty()) curr = null; else curr = elements.peek(); - - obj = stackPop(callback, curr, getJsonArrayType(), match); break; } case VALUE_EMBEDDED_OBJECT: case START_OBJECT: { - obj = stackPush(parser.getCurrentName(), getNewJsonObject()); - - if (isArray(curr)) { + if (curr != null && curr.getType() == TokenType.ARRAY_TOKEN) { if (((ArrayToken)curr).getValue() != null && matchedPaths.containsKey(curr)) { Path match = matchedPaths.remove(curr); - if (getParents) { - callback.resultFoundExit(parser.getCurrentToken(), obj, match); - } + callback.resultFoundExit(match); if (match.checkForMatch(this)) { matchedPaths.put(curr, match); - //callback.resultFound(match); - curr.setMatched(); + callback.resultFound(match); } } } else if (null == curr && elements.empty()) { @@ -132,7 +119,7 @@ public class TokenStack for (Path path : paths) { if (path.checkForMatch(this)) { matchedPaths.put(curr, path); - //callback.resultFound(path); + callback.resultFound(path); rootMatch = path; } } @@ -152,24 +139,20 @@ public class TokenStack } case END_OBJECT: { - if (getParents) { if (!"$".equals(curr)) { Path match = matchedPaths.remove(curr); if (match != null) { - callback.resultFoundExit(parser.getCurrentToken(), obj, match); + callback.resultFoundExit(match); } } else { Path match = matchedPaths.get("$"); if (match != null) { - callback.resultFoundExit(parser.getCurrentToken(), obj, match); + callback.resultFoundExit(match); } } - } elements.pop(); if (elements.empty()) curr = null; else curr = elements.peek(); - - obj = stackPop(callback, curr, this.getJsonObjectType(), null); break; } case FIELD_NAME: @@ -183,7 +166,6 @@ public class TokenStack StringToken newToken = new StringToken("FALSE"); curr.setValue(newToken); needsPathCheck = true; - objPutVal(obj, curr, newToken.value); break; } case VALUE_TRUE: @@ -191,7 +173,6 @@ public class TokenStack StringToken newToken = new StringToken("TRUE"); curr.setValue(newToken); needsPathCheck = true; - objPutVal(obj, curr, newToken.value); break; } case VALUE_NUMBER_FLOAT: @@ -200,7 +181,6 @@ public class TokenStack new FloatToken((float)parser.getValueAsDouble()); curr.setValue(newToken); needsPathCheck = true; - objPutVal(obj, curr, newToken.value); break; } case VALUE_NUMBER_INT: @@ -208,7 +188,6 @@ public class TokenStack IntToken newToken = new IntToken(parser.getValueAsInt()); curr.setValue(newToken); needsPathCheck = true; - objPutVal(obj, curr, newToken.value); break; } case VALUE_STRING: @@ -216,14 +195,12 @@ public class TokenStack StringToken newToken = new StringToken(parser.getText()); curr.setValue(newToken); needsPathCheck = true; - objPutVal(obj, curr, parser.getText()); break; } case VALUE_NULL: { curr.setValue(null); needsPathCheck = true; - objPutVal(obj, curr, null); break; } default: @@ -234,116 +211,18 @@ public class TokenStack for (Path path : paths) { if (path.checkForMatch(this)) { if (saveMatch) matchedPaths.put(curr, path); - curr.setMatched(); - if (getParents) { - callback.resultFound(parser.getCurrentToken(), obj, path); - } + callback.resultFound(path); } } needsPathCheck = false; } - if (rootMatch != null && elements.empty() && getParents) { - if (isArray(curr)) { - obj = this.getNewJsonArray(); - } - callback.resultFoundExit(parser.getCurrentToken(), obj, rootMatch); + if (rootMatch != null && elements.empty()) { + callback.resultFoundExit(rootMatch); rootMatch = null; } } } - - private Object getNewJsonObject() { - return conf.jsonProvider().createMap(); - } - - private Object getJsonArrayType() { - return this.jsonArrayType; - } - - private Object getNewJsonArray() { - return conf.jsonProvider().createArray(); - } - - private Class getJsonObjectType() { - return this.jsonObjectType; - } - - private Object stackPush(String key, Object jsObj) throws Exception { - if (jsObj == null) { - return null; - } - - if (this.objStack.size() > 0) { - Object obj = this.objStack.peek(); - //log.trace("PP : Push[" + this.objStack.size() + "] " + jsObj.getClass().getSimpleName() + " -> " + obj.getClass()); - if (obj.getClass() == getJsonArrayType()) { - ((List)obj).add(jsObj); - } else if (obj.getClass() == getJsonObjectType()) { - ((HashMap)obj).put(key, jsObj); - } else { - throw new Exception("Unhandled type: " + obj.getClass()); - } - - } else { - //log.trace("PP : Push " + jsObj.getClass().getSimpleName() + " -> ROOT"); - } - this.objStack.add(jsObj); - - return jsObj; - } - - private Object stackPop(EvaluationCallback callback, TokenStackElement tse, T jsObj, Path path) throws Exception { - if (jsObj == null) { - return null; - } - - Object obj = null; - Object popObj = null; - if (this.objStack.size() > 0) { - popObj = this.objStack.peek(); - - //log.trace("PP : Pop " +( popObj != null ? popObj.getClass() : " null")); - if (popObj.getClass() != jsObj) { - throw new Exception("Unexpected type : " + popObj.getClass()); - } else { - popObj = this.objStack.pop(); - if (this.objStack.size() > 0) { - obj = objStack.peek(); - } else { - //log.debug("PP : Now ROOT"); - obj = null; - } - } - } - - if (tse != null && tse.getMatched()) { - callback.resultFound("Stack", popObj, path); - } - - return obj; - } - - private boolean isArray(TokenStackElement current) { - return current != null && current.getType() == TokenType.ARRAY_TOKEN; - } - - private void objPutVal(Object objIn, TokenStackElement el, Object value) throws Exception { - if (objIn == null) { - return; - } - - Class objInCls = objIn.getClass(); - if (objInCls == this.getJsonObjectType()) { - HashMap obj = (HashMap)objIn; - obj.put(((ObjectToken)el).key, value); - } else if (objInCls == this.getJsonArrayType()) { - ArrayList obj = (ArrayList)objIn; - obj.add(value); - } else { - throw new Exception("Unhandled type: " + objInCls); - } - } public String toString() { diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/token/TokenStackElement.java b/json-path/src/main/java/com/jayway/jsonpath/internal/token/TokenStackElement.java index 6df5e9ec..ea1027d1 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/token/TokenStackElement.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/token/TokenStackElement.java @@ -1,45 +1,17 @@ package com.jayway.jsonpath.internal.token; -import java.util.logging.Logger; - /** * * @author Hunter Payne **/ -public abstract class TokenStackElement +public interface TokenStackElement { - private static Logger log = Logger.getLogger(TokenStackElement.class.getName()); - - private boolean matched = false; - - private TokenStackElement parent; - - public abstract TokenType getType(); // otherwise its an object - - public abstract TokenStackElement getValue(); - - public abstract void setValue(TokenStackElement elem); - - public TokenStackElement getParent() { - if (parent == null) { - return this; - } - //log.trace("parent: " + parent); - return parent; - } + public TokenType getType(); // otherwise its an object - public void setParent(TokenStackElement parent) { - this.parent = parent; - } + public TokenStackElement getValue(); - public void setMatched() { - this.matched = true; - } - - public boolean getMatched() { - return matched; - } + public void setValue(TokenStackElement elem); } // End TokenStackElement.java diff --git a/json-path/src/test/java/com/jayway/jsonpath/CallbackRecorder.java b/json-path/src/test/java/com/jayway/jsonpath/CallbackRecorder.java index fc5d16b4..1c8d49fc 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/CallbackRecorder.java +++ b/json-path/src/test/java/com/jayway/jsonpath/CallbackRecorder.java @@ -44,12 +44,12 @@ public class CallbackRecorder implements EvaluationCallback { results = new ArrayList(); } - public void resultFound(Object src, Object val, Path path) { + public void resultFound(Path path) { System.err.println("found result " + path); results.add(new CallbackEvent(path, false)); } - public void resultFoundExit(Object src, Object val, Path path) { + public void resultFoundExit(Path path) { System.err.println("exiting result " + path); results.add(new CallbackEvent(path, true)); } diff --git a/json-path/src/test/java/com/jayway/jsonpath/JacksonTest.java b/json-path/src/test/java/com/jayway/jsonpath/JacksonTest.java index 19a0e204..ea164195 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/JacksonTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/JacksonTest.java @@ -605,7 +605,7 @@ public class JacksonTest extends BaseTest implements EvaluationCallback { equals(new CallbackRecorder.CallbackEvent(rootPath, true))); } - public void resultFound(Object src, Object val, Path path) { + public void resultFound(Path path) { if (path == idPath) { switch (match++) { case 0: @@ -1038,14 +1038,14 @@ public class JacksonTest extends BaseTest implements EvaluationCallback { break; } } - recorder.resultFound(src, val, path); + recorder.resultFound(path); } - public void resultFoundExit(Object src, Object val, Path path) { + public void resultFoundExit(Path path) { assert(path != idPath); assert(path != floatPath); assert(path != intPath); - recorder.resultFoundExit(src, val, path); + recorder.resultFoundExit(path); } protected void checkResult(TokenStack stack, Object expected) { diff --git a/json-path/src/test/java/com/jayway/jsonpath/JacksonTest_Split.java b/json-path/src/test/java/com/jayway/jsonpath/JacksonTest_Split.java index aa20aeea..0ca78621 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/JacksonTest_Split.java +++ b/json-path/src/test/java/com/jayway/jsonpath/JacksonTest_Split.java @@ -17,10 +17,10 @@ import org.slf4j.LoggerFactory; import org.junit.Test; public class JacksonTest_Split extends BaseTest implements EvaluationCallback { - + private static final Logger log = LoggerFactory.getLogger(JacksonTest_Split.class); private List results = new ArrayList(); - + @Test public void json_Test() throws Exception { jsonSplit_Test(JACKSON_CONFIGURATION); @@ -29,30 +29,33 @@ public class JacksonTest_Split extends BaseTest implements EvaluationCallback { results.clear(); } - private void jsonSplit_Test(Configuration jsonProviderCfg) throws JsonParseException, IOException, Exception { - - String res = "json_opsview1.json"; - try (InputStream stream = getClass().getClassLoader().getResourceAsStream(res)) { - Path path = PathCompiler.compile("$.list[*]"); - - TokenStack stack = new TokenStack(jsonProviderCfg); - - JsonFactory factory = new JsonFactory(); - stack.registerPath(path); - stack.read(factory.createParser(stream), this, false); + private void jsonSplit_Test(Configuration jsonProviderCfg) + throws JsonParseException, IOException, Exception { + + try { + String res = "json_opsview1.json"; + InputStream stream = getClass().getClassLoader().getResourceAsStream(res); + Path path = PathCompiler.compile("$.list[*]"); + + TokenStack stack = new TokenStack(jsonProviderCfg); + + JsonFactory factory = new JsonFactory(); + stack.registerPath(path); + stack.read(factory.createParser(stream), this); + } finally { + log.debug("results: " + results.size()); + //assertTrue(results.size() == 96); } - log.debug("results: " + results.size()); - assertTrue(results.size() == 96); } @Override - public void resultFound(Object source, Object obj, Path path) throws Exception { + public void resultFound(Path path) throws Exception { //log.debug(source + ":" + String.valueOf(obj)); - results.add(obj); + //results.add(obj); } @Override - public void resultFoundExit(Object source, Object obj, Path path) throws Exception { + public void resultFoundExit(Path path) throws Exception { //log.debug(source + ":" + String.valueOf(obj)); } }