You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2017/01/13 11:30:51 UTC
[2/3] camel git commit: CAMEL-10702: camel-jsonpath - Have an easy
way of defining predicates with a single operator instead of having to grok
the half complex style of jsonpath.
CAMEL-10702: camel-jsonpath - Have an easy way of defining predicates with a single operator instead of having to grok the half complex style of jsonpath.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/cfbe791d
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/cfbe791d
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/cfbe791d
Branch: refs/heads/master
Commit: cfbe791d6f08f5a4063f7b93555563e041adf98c
Parents: 69a19a3
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Jan 13 11:33:15 2017 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Jan 13 12:30:42 2017 +0100
----------------------------------------------------------------------
.../camel/jsonpath/JsonPathExpression.java | 22 ++++-
.../apache/camel/jsonpath/JsonPathLanguage.java | 2 +
.../easypredicate/EasyPredicateOperators.java | 96 ++++++++++++++++++++
.../easypredicate/EasyPredicateParser.java | 70 ++++++++++++++
.../jsonpath/JsonPathWithEvenSimpleCBRTest.java | 80 ++++++++++++++++
5 files changed, 268 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/cfbe791d/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java
index 37eeab1..3e79f9a 100644
--- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java
+++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java
@@ -22,6 +22,7 @@ import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.ExpressionEvaluationException;
import org.apache.camel.ExpressionIllegalSyntaxException;
+import org.apache.camel.jsonpath.easypredicate.EasyPredicateParser;
import org.apache.camel.support.ExpressionAdapter;
public class JsonPathExpression extends ExpressionAdapter implements AfterPropertiesConfigured {
@@ -29,6 +30,7 @@ public class JsonPathExpression extends ExpressionAdapter implements AfterProper
private final String expression;
private JsonPathEngine engine;
+ private boolean predicate;
private Class<?> resultType;
private boolean suppressExceptions;
private boolean allowSimple = true;
@@ -38,6 +40,17 @@ public class JsonPathExpression extends ExpressionAdapter implements AfterProper
this.expression = expression;
}
+ public boolean isPredicate() {
+ return predicate;
+ }
+
+ /**
+ * Whether to be evaluated as a predicate
+ */
+ public void setPredicate(boolean predicate) {
+ this.predicate = predicate;
+ }
+
public Class<?> getResultType() {
return resultType;
}
@@ -102,10 +115,15 @@ public class JsonPathExpression extends ExpressionAdapter implements AfterProper
}
public void init() {
+ String exp = expression;
+ if (predicate) {
+ EasyPredicateParser parser = new EasyPredicateParser();
+ exp = parser.parse(expression);
+ }
try {
- engine = new JsonPathEngine(expression, suppressExceptions, allowSimple, options);
+ engine = new JsonPathEngine(exp, suppressExceptions, allowSimple, options);
} catch (Exception e) {
- throw new ExpressionIllegalSyntaxException(expression, e);
+ throw new ExpressionIllegalSyntaxException(exp, e);
}
}
http://git-wip-us.apache.org/repos/asf/camel/blob/cfbe791d/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java
index 297823b..d2e4d0b 100644
--- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java
+++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java
@@ -58,6 +58,7 @@ public class JsonPathLanguage extends LanguageSupport {
@Override
public Predicate createPredicate(final String predicate) {
JsonPathExpression answer = new JsonPathExpression(predicate);
+ answer.setPredicate(true);
answer.setResultType(resultType);
answer.setSuppressExceptions(suppressExceptions);
answer.setOptions(options);
@@ -68,6 +69,7 @@ public class JsonPathLanguage extends LanguageSupport {
@Override
public Expression createExpression(final String expression) {
JsonPathExpression answer = new JsonPathExpression(expression);
+ answer.setPredicate(false);
answer.setResultType(resultType);
answer.setSuppressExceptions(suppressExceptions);
answer.setOptions(options);
http://git-wip-us.apache.org/repos/asf/camel/blob/cfbe791d/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/easypredicate/EasyPredicateOperators.java
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/easypredicate/EasyPredicateOperators.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/easypredicate/EasyPredicateOperators.java
new file mode 100644
index 0000000..4f49504
--- /dev/null
+++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/easypredicate/EasyPredicateOperators.java
@@ -0,0 +1,96 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 org.apache.camel.jsonpath.easypredicate;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+public class EasyPredicateOperators {
+
+ private static final String EQ = "==";
+ private static final String NE = "!=";
+ private static final String LT = "<";
+ private static final String LE = "<=";
+ private static final String GT = ">";
+ private static final String GE = ">=";
+ private static final String REG = "=~";
+ private static final String IN = "in";
+ private static final String NIN = "nin";
+ private static final String SIZE = "size";
+ private static final String EMPTY = "empty";
+
+ private static final String[] OPS = new String[]{EQ, NE, LT, LE, GT, GE, REG, IN, NIN, SIZE, EMPTY};
+
+ private static final Pattern PATTERN = Pattern.compile("\\s(" + Arrays.stream(OPS).collect(Collectors.joining("|")) + ")\\s");
+
+ /**
+ * Does the expression have any operator?
+ */
+ public static boolean hasOperator(String exp) {
+ return Arrays.stream(OPS).anyMatch(o -> exp.contains(" " + o + ""));
+ }
+
+ /**
+ * Is this an operator
+ */
+ static boolean isOperator(String exp) {
+ return Arrays.stream(OPS).anyMatch(s -> Objects.equals(s, exp));
+ }
+
+ /**
+ * Gets the operator
+ */
+ static String getOperatorAtStart(String exp) {
+ return Arrays.stream(OPS).filter(o -> exp.startsWith(" " + o + "")).findFirst().orElse(null);
+ }
+
+ public static String[] tokens(String exp) {
+ List<String> list = new ArrayList<>();
+
+ StringBuilder part = new StringBuilder();
+ for (int i = 0; i < exp.length(); i++) {
+
+ // is there a new operator
+ String s = exp.substring(i);
+ String op = getOperatorAtStart(s);
+ if (op != null) {
+ if (part.length() > 0) {
+ list.add(part.toString());
+ part.setLength(0);
+ }
+ list.add(op.trim());
+ // move i ahead
+ i = i + op.length() + 1;
+ } else {
+ char ch = exp.charAt(i);
+ part.append(ch);
+ }
+ }
+
+ // ant leftovers
+ if (part.length() > 0) {
+ list.add(part.toString());
+ }
+
+ return list.toArray(new String[list.size()]);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/cfbe791d/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/easypredicate/EasyPredicateParser.java
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/easypredicate/EasyPredicateParser.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/easypredicate/EasyPredicateParser.java
new file mode 100644
index 0000000..f523f46
--- /dev/null
+++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/easypredicate/EasyPredicateParser.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 org.apache.camel.jsonpath.easypredicate;
+
+import static org.apache.camel.jsonpath.easypredicate.EasyPredicateOperators.hasOperator;
+import static org.apache.camel.jsonpath.easypredicate.EasyPredicateOperators.isOperator;
+import static org.apache.camel.jsonpath.easypredicate.EasyPredicateOperators.tokens;
+
+public class EasyPredicateParser {
+
+ public String parse(String exp) {
+ if (exp.startsWith("$")) {
+ // regular json path so skip
+ return exp;
+ }
+
+ // must have an operator
+ if (!hasOperator(exp)) {
+ return exp;
+ }
+
+ StringBuilder sb = new StringBuilder();
+
+ // grab before operator
+ String[] parts = tokens(exp);
+
+ // only support one operator currently
+ if (parts.length == 3) {
+ String prev = parts[0];
+ String op = parts[1];
+ String next = parts[2];
+ if (isOperator(op)) {
+ int pos = prev.lastIndexOf(".");
+ String before = prev.substring(0, pos);
+ String after = prev.substring(pos + 1);
+ sb.append("$");
+ if (!before.startsWith(".")) {
+ sb.append(".");
+ }
+ sb.append(before);
+ sb.append("[?(@.");
+ sb.append(after);
+ sb.append(" ");
+ sb.append(op);
+ sb.append(" ");
+ sb.append(next);
+ sb.append(")]");
+ }
+ return sb.toString();
+ }
+
+ // not able to parse so return as-is
+ return exp;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/cfbe791d/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathWithEvenSimpleCBRTest.java
----------------------------------------------------------------------
diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathWithEvenSimpleCBRTest.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathWithEvenSimpleCBRTest.java
new file mode 100644
index 0000000..8db54d5
--- /dev/null
+++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathWithEvenSimpleCBRTest.java
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.jsonpath;
+
+import java.io.File;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class JsonPathWithEvenSimpleCBRTest extends CamelTestSupport {
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .choice()
+ .when().jsonpath("store.book.price < ${header.cheap}")
+ .to("mock:cheap")
+ .when().jsonpath("store.book.price < ${header.average}")
+ .to("mock:average")
+ .otherwise()
+ .to("mock:expensive");
+ }
+ };
+ }
+
+ @Test
+ public void testCheap() throws Exception {
+ getMockEndpoint("mock:cheap").expectedMessageCount(1);
+ getMockEndpoint("mock:average").expectedMessageCount(0);
+ getMockEndpoint("mock:expensive").expectedMessageCount(0);
+
+ fluentTemplate.withHeader("cheap", 10).withHeader("average", 30).withBody(new File("src/test/resources/cheap.json"))
+ .to("direct:start").send();
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Test
+ public void testAverage() throws Exception {
+ getMockEndpoint("mock:cheap").expectedMessageCount(0);
+ getMockEndpoint("mock:average").expectedMessageCount(1);
+ getMockEndpoint("mock:expensive").expectedMessageCount(0);
+
+ fluentTemplate.withHeader("cheap", 10).withHeader("average", 30).withBody(new File("src/test/resources/average.json"))
+ .to("direct:start").send();
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Test
+ public void testExpensive() throws Exception {
+ getMockEndpoint("mock:cheap").expectedMessageCount(0);
+ getMockEndpoint("mock:average").expectedMessageCount(0);
+ getMockEndpoint("mock:expensive").expectedMessageCount(1);
+
+ fluentTemplate.withHeader("cheap", 10).withHeader("average", 30).withBody(new File("src/test/resources/expensive.json"))
+ .to("direct:start").send();
+
+ assertMockEndpointsSatisfied();
+ }
+
+}