Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
472 changes: 469 additions & 3 deletions json-path/src/main/java/com/jayway/jsonpath/Criteria.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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;

import com.jayway.jsonpath.internal.Path;

/**
* A listener that can be registered on a {@link com.jayway.jsonpath.internal.token.TokenStack} that is notified when a
* result is found for a specific registered path
*/
public interface EvaluationCallback {

/**
* Callback invoked when result is found
* @param path -- the specific path that was triggered
*/
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(Path path) throws Exception;
}
28 changes: 26 additions & 2 deletions json-path/src/main/java/com/jayway/jsonpath/Filter.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package com.jayway.jsonpath;

import com.jayway.jsonpath.internal.Utils;
import com.jayway.jsonpath.internal.token.TokenStack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -28,7 +29,7 @@
/**
*
*/
public abstract class Filter implements Predicate {
public abstract class Filter implements StreamingPredicate {

private static final Logger logger = LoggerFactory.getLogger(Filter.class);
private static final Pattern OPERATOR_SPLIT = Pattern.compile("((?<=&&|\\|\\|)|(?=&&|\\|\\|))");
Expand Down Expand Up @@ -56,6 +57,8 @@ public static Filter filter(Collection<Predicate> predicates) {
@Override
public abstract boolean apply(PredicateContext ctx);

@Override
public abstract boolean check(TokenStack stack, int idx);

public Filter or(final Predicate other){
return new OrFilter(this, other);
Expand All @@ -80,6 +83,11 @@ public boolean apply(PredicateContext ctx) {
return predicate.apply(ctx);
}

@Override
public boolean check(TokenStack stack, int idx) {
return ((StreamingPredicate)predicate).check(stack, idx);
}

@Override
public String toString() {
return predicate.toString();
Expand Down Expand Up @@ -114,6 +122,16 @@ public boolean apply(PredicateContext ctx) {
return true;
}

@Override
public boolean check(TokenStack stack, int idx) {
for (Predicate predicate : predicates) {
if(!((StreamingPredicate)predicate).check(stack, idx)){
return false;
}
}
return true;
}

@Override
public String toString() {
return "(" + Utils.join(" && ", predicates) + ")";
Expand All @@ -124,7 +142,7 @@ private static final class OrFilter extends Filter {

private final Predicate left;
private final Predicate right;

private OrFilter(Predicate left, Predicate right) {
this.left = left;
this.right = right;
Expand All @@ -140,6 +158,12 @@ public boolean apply(PredicateContext ctx) {
return a || right.apply(ctx);
}

@Override
public boolean check(TokenStack stack, int idx) {
boolean a = ((StreamingPredicate)left).check(stack, idx);
return a || ((StreamingPredicate)right).check(stack, idx);
}

@Override
public String toString() {
return "(" + left.toString() + " || " + right.toString() + ")";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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;

import com.jayway.jsonpath.internal.token.TokenStack;

/**
*
*/
public interface StreamingPredicate extends Predicate {

boolean check(TokenStack stack, int idx);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.internal.token.EvaluationContextImpl;
import com.jayway.jsonpath.internal.token.PathToken;
import com.jayway.jsonpath.internal.token.TokenStack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -61,6 +62,11 @@ public EvaluationContext evaluate(Object document, Object rootDocument, Configur
return evaluate(document, rootDocument, configuration, false);
}

@Override
public boolean checkForMatch(TokenStack stack) {
return root.checkForMatch(stack, 0);
}

@Override
public boolean isDefinite() {
return root.isPathDefinite();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package com.jayway.jsonpath.internal;

import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.internal.token.TokenStack;

/**
*
Expand Down Expand Up @@ -43,6 +44,12 @@ public interface Path {
*/
EvaluationContext evaluate(Object document, Object rootDocument, Configuration configuration, boolean forUpdate);

/**
* checks the parser state represented by stack and determines if this
* path matches it
*/
boolean checkForMatch(TokenStack stack);

/**
*
* @return true id this path is definite
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,85 @@ public String getPathFragment() {
return sb.toString();
}

@Override
public boolean checkForMatch(TokenStack stack, int idx)
{
if (stack.getStack().size() <= idx) return false;
TokenStackElement curr = stack.getStack().get(idx);

if (curr.getType() == TokenType.ARRAY_TOKEN) {
ArrayToken token = (ArrayToken)curr;
int tokenIdx = token.getIndex();
switch (operation) {
case CONTEXT_SIZE:
{
if (isLeaf()) {
return stack.getStack().size() - 1 == idx;
}
return next().checkForMatch(stack, idx + 1);
}
case SLICE_TO:
{
int to = criteria.get(0).intValue();
if (tokenIdx < to) {
if (isLeaf()) {
return stack.getStack().size() - 1 == idx;
}
return next().checkForMatch(stack, idx + 1);
}
break;
}
case SLICE_FROM:
{
int from = criteria.get(0).intValue();
if (from <= tokenIdx) {
if (isLeaf()) {
return stack.getStack().size() - 1 == idx;
}
return next().checkForMatch(stack, idx + 1);
}
break;
}
case SLICE_BETWEEN:
{
int from = criteria.get(0).intValue();
int to = criteria.get(1).intValue();
if (from <= tokenIdx && tokenIdx < to) {
if (isLeaf()) {
return stack.getStack().size() - 1 == idx;
}
return next().checkForMatch(stack, idx + 1);
}
break;
}
case INDEX_SEQUENCE:
{
for (Integer i : criteria) {
if (i.intValue() == tokenIdx) {
if (isLeaf()) {
return stack.getStack().size() - 1 == idx;
}
return next().checkForMatch(stack, idx + 1);
}
}
break;
}
case SINGLE_INDEX:
{
if (criteria.get(0).intValue() == tokenIdx) {
if (isLeaf()) {
return stack.getStack().size() - 1 == idx;
}
return next().checkForMatch(stack, idx + 1);
}
break;
}
}
}

return false;
}

@Override
boolean isTokenDefinite() {
return isDefinite;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

package com.jayway.jsonpath.internal.token;

/**
*
* @author Hunter Payne
**/
public class ArrayToken implements TokenStackElement
{
int currentIndex;
TokenStackElement value; // can be an object, array, or property

public ArrayToken()
{
currentIndex = 0;
value = null;
}

public TokenType getType()
{
return TokenType.ARRAY_TOKEN;
}

public int getIndex()
{
return currentIndex;
}

public TokenStackElement getValue()
{
return value;
}

public void setValue(TokenStackElement elem)
{
if (value != null) {
++currentIndex;
}
value = elem;
}

public String toString()
{
return "Array[idx=" + currentIndex + "]";
}
}

// End ArrayToken.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

package com.jayway.jsonpath.internal.token;

/**
*
* @author Hunter Payne
**/
public class FloatToken implements TokenStackElement
{
public float value;

public FloatToken(float f)
{
value = f;
}

public TokenType getType()
{
return TokenType.FLOAT_TOKEN;
}

public TokenStackElement getValue()
{
return null;
}

public void setValue(TokenStackElement elem)
{
throw new RuntimeException();
}
}

// End FloatToken.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

package com.jayway.jsonpath.internal.token;

/**
*
* @author Hunter Payne
**/
public class IntToken implements TokenStackElement
{
public int value;

public IntToken(int f)
{
value = f;
}

public TokenType getType()
{
return TokenType.INTEGER_TOKEN;
}

public TokenStackElement getValue()
{
return null;
}

public void setValue(TokenStackElement elem)
{
throw new RuntimeException();
}
}

// End IntToken.java
Loading