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/06/19 06:34:32 UTC
[2/2] camel git commit: CAMEL-11421: Up in the sky coding. Tokenize
language can now set the group size using dynamic values based on simple
language like some of the other options can do.
CAMEL-11421: Up in the sky coding. Tokenize language can now set the group size using dynamic values based on simple language like some of the other options can do.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/2f8b0190
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/2f8b0190
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/2f8b0190
Branch: refs/heads/master
Commit: 2f8b019062652a1f94728dac7ef9dc70d53c21fb
Parents: 848512f
Author: Claus Ibsen <da...@apache.org>
Authored: Sun Jun 18 15:49:31 2017 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Mon Jun 19 08:34:17 2017 +0200
----------------------------------------------------------------------
camel-core/src/main/docs/tokenize-language.adoc | 2 +-
.../apache/camel/builder/ExpressionBuilder.java | 28 ++++++++--
.../apache/camel/builder/ExpressionClause.java | 25 +++++++++
.../camel/builder/ExpressionClauseSupport.java | 30 +++++++++-
.../org/apache/camel/builder/ValueBuilder.java | 6 +-
.../language/tokenizer/TokenizeLanguage.java | 10 ++--
.../model/language/TokenizerExpression.java | 10 ++--
.../SplitTokenizerGroupDynamicTest.java | 59 ++++++++++++++++++++
.../SpringSplitTokenizerGroupDynamicTest.java | 32 +++++++++++
.../SpringSplitTokenizerGroupDynamicTest.xml | 46 +++++++++++++++
10 files changed, 226 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/2f8b0190/camel-core/src/main/docs/tokenize-language.adoc
----------------------------------------------------------------------
diff --git a/camel-core/src/main/docs/tokenize-language.adoc b/camel-core/src/main/docs/tokenize-language.adoc
index 8d5daf0..25ade1c 100644
--- a/camel-core/src/main/docs/tokenize-language.adoc
+++ b/camel-core/src/main/docs/tokenize-language.adoc
@@ -30,7 +30,7 @@ The Tokenize language supports 10 options which are listed below.
| regex | false | Boolean | If the token is a regular expression pattern. The default value is false
| xml | false | Boolean | Whether the input is XML messages. This option must be set to true if working with XML payloads.
| includeTokens | false | Boolean | Whether to include the tokens in the parts when using pairs The default value is false
-| group | | Integer | To group N parts together for example to split big files into chunks of 1000 lines.
+| group | | String | To group N parts together for example to split big files into chunks of 1000 lines. You can use simple language as the group to support dynamic group sizes.
| skipFirst | false | Boolean | To skip the very first element
| trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks
|=======================================================================
http://git-wip-us.apache.org/repos/asf/camel/blob/2f8b0190/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java b/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
index 60b2300..6fdc509 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
@@ -40,12 +40,14 @@ import org.apache.camel.Component;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.Expression;
+import org.apache.camel.ExpressionEvaluationException;
import org.apache.camel.InvalidPayloadException;
import org.apache.camel.Message;
import org.apache.camel.NoSuchEndpointException;
import org.apache.camel.NoSuchLanguageException;
import org.apache.camel.NoTypeConversionAvailableException;
import org.apache.camel.Producer;
+import org.apache.camel.RuntimeExchangeException;
import org.apache.camel.component.bean.BeanInvocation;
import org.apache.camel.component.properties.PropertiesComponent;
import org.apache.camel.language.bean.BeanLanguage;
@@ -1639,14 +1641,21 @@ public final class ExpressionBuilder {
};
}
- public static Expression groupXmlIteratorExpression(final Expression expression, final int group) {
+ public static Expression groupXmlIteratorExpression(final Expression expression, final String group) {
return new ExpressionAdapter() {
public Object evaluate(Exchange exchange) {
// evaluate expression as iterator
Iterator<?> it = expression.evaluate(exchange, Iterator.class);
ObjectHelper.notNull(it, "expression: " + expression + " evaluated on " + exchange + " must return an java.util.Iterator");
// must use GroupTokenIterator in xml mode as we want to concat the xml parts into a single message
- return new GroupTokenIterator(exchange, it, null, group, false);
+ // the group can be a simple expression so evaluate it as a number
+ Integer parts = exchange.getContext().resolveLanguage("simple").createExpression(group).evaluate(exchange, Integer.class);
+ if (parts == null) {
+ throw new RuntimeExchangeException("Group evaluated as null, must be evaluated as a positive Integer value from expression: " + group, exchange);
+ } else if (parts <= 0) {
+ throw new RuntimeExchangeException("Group must be a positive number, was: " + parts, exchange);
+ }
+ return new GroupTokenIterator(exchange, it, null, parts, false);
}
@Override
@@ -1656,16 +1665,23 @@ public final class ExpressionBuilder {
};
}
- public static Expression groupIteratorExpression(final Expression expression, final String token, final int group, final boolean skipFirst) {
+ public static Expression groupIteratorExpression(final Expression expression, final String token, final String group, final boolean skipFirst) {
return new ExpressionAdapter() {
public Object evaluate(Exchange exchange) {
// evaluate expression as iterator
Iterator<?> it = expression.evaluate(exchange, Iterator.class);
ObjectHelper.notNull(it, "expression: " + expression + " evaluated on " + exchange + " must return an java.util.Iterator");
+ // the group can be a simple expression so evaluate it as a number
+ Integer parts = exchange.getContext().resolveLanguage("simple").createExpression(group).evaluate(exchange, Integer.class);
+ if (parts == null) {
+ throw new RuntimeExchangeException("Group evaluated as null, must be evaluated as a positive Integer value from expression: " + group, exchange);
+ } else if (parts <= 0) {
+ throw new RuntimeExchangeException("Group must be a positive number, was: " + parts, exchange);
+ }
if (token != null) {
- return new GroupTokenIterator(exchange, it, token, group, skipFirst);
+ return new GroupTokenIterator(exchange, it, token, parts, skipFirst);
} else {
- return new GroupIterator(exchange, it, group, skipFirst);
+ return new GroupIterator(exchange, it, parts, skipFirst);
}
}
@@ -2382,7 +2398,7 @@ public final class ExpressionBuilder {
public Object evaluate(Exchange exchange) {
// use simple language
Expression exp = exchange.getContext().resolveLanguage("simple").createExpression(expression);
- return ExpressionBuilder.groupIteratorExpression(exp, null, group, false).evaluate(exchange, Object.class);
+ return ExpressionBuilder.groupIteratorExpression(exp, null, "" + group, false).evaluate(exchange, Object.class);
}
@Override
http://git-wip-us.apache.org/repos/asf/camel/blob/2f8b0190/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java b/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java
index 07e9c85..05fd859 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java
@@ -679,6 +679,18 @@ public class ExpressionClause<T> extends ExpressionDefinition {
* @param token the token
* @param regex whether the token is a regular expression or not
* @param group to group by the given number
+ * @return the builder to continue processing the DSL
+ */
+ public T tokenize(String token, boolean regex, String group) {
+ return tokenize(token, regex, group, false);
+ }
+
+ /**
+ * Evaluates a token expression on the message body
+ *
+ * @param token the token
+ * @param regex whether the token is a regular expression or not
+ * @param group to group by the given number
* @param skipFirst whether to skip the first element
* @return the builder to continue processing the DSL
*/
@@ -690,6 +702,19 @@ public class ExpressionClause<T> extends ExpressionDefinition {
* Evaluates a token expression on the message body
*
* @param token the token
+ * @param regex whether the token is a regular expression or not
+ * @param group to group by the given number
+ * @param skipFirst whether to skip the first element
+ * @return the builder to continue processing the DSL
+ */
+ public T tokenize(String token, boolean regex, String group, boolean skipFirst) {
+ return delegate.tokenize(token, null, regex, group, skipFirst);
+ }
+
+ /**
+ * Evaluates a token expression on the message body
+ *
+ * @param token the token
* @param group to group by the given number
* @return the builder to continue processing the DSL
*/
http://git-wip-us.apache.org/repos/asf/camel/blob/2f8b0190/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java b/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java
index 910645f..64cef85 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java
@@ -708,6 +708,20 @@ public class ExpressionClauseSupport<T> {
* @return the builder to continue processing the DSL
*/
public T tokenize(String token, String headerName, boolean regex, int group, boolean skipFirst) {
+ return tokenize(token, headerName, regex, "" + group, skipFirst);
+ }
+
+ /**
+ * Evaluates a token expression on the given header
+ *
+ * @param token the token
+ * @param headerName name of header to tokenize
+ * @param regex whether the token is a regular expression or not
+ * @param group to group by number of parts
+ * @param skipFirst whether to skip the very first element
+ * @return the builder to continue processing the DSL
+ */
+ public T tokenize(String token, String headerName, boolean regex, String group, boolean skipFirst) {
TokenizerExpression expression = new TokenizerExpression();
expression.setToken(token);
expression.setHeaderName(headerName);
@@ -744,13 +758,23 @@ public class ExpressionClauseSupport<T> {
* @return the builder to continue processing the DSL
*/
public T tokenizeXMLPair(String tagName, String inheritNamespaceTagName, int group) {
+ return tokenizeXMLPair(tagName, inheritNamespaceTagName, "" + group);
+ }
+
+ /**
+ * Evaluates a token pair expression on the message body with XML content
+ *
+ * @param tagName the the tag name of the child nodes to tokenize
+ * @param inheritNamespaceTagName optional parent or root tag name that contains namespace(s) to inherit
+ * @param group to group by the given number
+ * @return the builder to continue processing the DSL
+ */
+ public T tokenizeXMLPair(String tagName, String inheritNamespaceTagName, String group) {
TokenizerExpression expression = new TokenizerExpression();
expression.setToken(tagName);
expression.setInheritNamespaceTagName(inheritNamespaceTagName);
expression.setXml(true);
- if (group > 0) {
- expression.setGroup(group);
- }
+ expression.setGroup(group);
setExpressionType(expression);
return result;
}
http://git-wip-us.apache.org/repos/asf/camel/blob/2f8b0190/camel-core/src/main/java/org/apache/camel/builder/ValueBuilder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/builder/ValueBuilder.java b/camel-core/src/main/java/org/apache/camel/builder/ValueBuilder.java
index 91b5fcd..eb87b11 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/ValueBuilder.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/ValueBuilder.java
@@ -185,8 +185,12 @@ public class ValueBuilder implements Expression, Predicate {
}
public ValueBuilder tokenize(String token, int group, boolean skipFirst) {
+ return tokenize(token, "" + group, skipFirst);
+ }
+
+ public ValueBuilder tokenize(String token, String group, boolean skipFirst) {
Expression newExp = ExpressionBuilder.tokenizeExpression(expression, token);
- if (group == 0 && skipFirst) {
+ if (group == null && skipFirst) {
// wrap in skip first (if group then it has its own skip first logic)
newExp = ExpressionBuilder.skipFirstExpression(newExp);
}
http://git-wip-us.apache.org/repos/asf/camel/blob/2f8b0190/camel-core/src/main/java/org/apache/camel/language/tokenizer/TokenizeLanguage.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/language/tokenizer/TokenizeLanguage.java b/camel-core/src/main/java/org/apache/camel/language/tokenizer/TokenizeLanguage.java
index 22b62a2..33bf48d 100644
--- a/camel-core/src/main/java/org/apache/camel/language/tokenizer/TokenizeLanguage.java
+++ b/camel-core/src/main/java/org/apache/camel/language/tokenizer/TokenizeLanguage.java
@@ -46,7 +46,7 @@ public class TokenizeLanguage implements Language, IsSingleton {
private boolean regex;
private boolean xml;
private boolean includeTokens;
- private int group;
+ private String group;
private boolean skipFirst;
public static Expression tokenize(String token) {
@@ -121,14 +121,14 @@ public class TokenizeLanguage implements Language, IsSingleton {
} else {
answer = ExpressionBuilder.tokenizeExpression(exp, token);
}
- if (group == 0 && skipFirst) {
+ if (group == null && skipFirst) {
// wrap in skip first (if group then it has its own skip first logic)
answer = ExpressionBuilder.skipFirstExpression(answer);
}
}
// if group then wrap answer in group expression
- if (group > 0) {
+ if (group != null) {
if (isXml()) {
answer = ExpressionBuilder.groupXmlIteratorExpression(answer, group);
} else {
@@ -202,11 +202,11 @@ public class TokenizeLanguage implements Language, IsSingleton {
this.includeTokens = includeTokens;
}
- public int getGroup() {
+ public String getGroup() {
return group;
}
- public void setGroup(int group) {
+ public void setGroup(String group) {
this.group = group;
}
http://git-wip-us.apache.org/repos/asf/camel/blob/2f8b0190/camel-core/src/main/java/org/apache/camel/model/language/TokenizerExpression.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/language/TokenizerExpression.java b/camel-core/src/main/java/org/apache/camel/model/language/TokenizerExpression.java
index 83aacd6..2099317 100644
--- a/camel-core/src/main/java/org/apache/camel/model/language/TokenizerExpression.java
+++ b/camel-core/src/main/java/org/apache/camel/model/language/TokenizerExpression.java
@@ -52,7 +52,7 @@ public class TokenizerExpression extends ExpressionDefinition {
@XmlAttribute
private Boolean includeTokens;
@XmlAttribute
- private Integer group;
+ private String group;
@XmlAttribute
private Boolean skipFirst;
@@ -149,14 +149,15 @@ public class TokenizerExpression extends ExpressionDefinition {
this.includeTokens = includeTokens;
}
- public Integer getGroup() {
+ public String getGroup() {
return group;
}
/**
* To group N parts together, for example to split big files into chunks of 1000 lines.
+ * You can use simple language as the group to support dynamic group sizes.
*/
- public void setGroup(Integer group) {
+ public void setGroup(String group) {
this.group = group;
}
@@ -193,9 +194,6 @@ public class TokenizerExpression extends ExpressionDefinition {
language.setIncludeTokens(includeTokens);
}
if (group != null) {
- if (group <= 0) {
- throw new IllegalArgumentException("Group must be a positive number, was: " + group);
- }
language.setGroup(group);
}
if (skipFirst != null) {
http://git-wip-us.apache.org/repos/asf/camel/blob/2f8b0190/camel-core/src/test/java/org/apache/camel/processor/SplitTokenizerGroupDynamicTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/processor/SplitTokenizerGroupDynamicTest.java b/camel-core/src/test/java/org/apache/camel/processor/SplitTokenizerGroupDynamicTest.java
new file mode 100644
index 0000000..53436a6
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/processor/SplitTokenizerGroupDynamicTest.java
@@ -0,0 +1,59 @@
+/**
+ * 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.processor;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+
+public class SplitTokenizerGroupDynamicTest extends ContextTestSupport {
+
+ public void testSplitTokenizerA() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:split");
+ mock.expectedBodiesReceived("Claus,James", "Willem");
+
+ template.sendBodyAndHeader("direct:a", "Claus,James,Willem", "groups", 2);
+
+ assertMockEndpointsSatisfied();
+ }
+
+ public void testSplitTokenizerB() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:split");
+ mock.expectedBodiesReceived("James,Willem");
+
+ template.sendBodyAndHeader("direct:b", "Claus,James,Willem".getBytes(), "groups", 2);
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
+ from("direct:a")
+ .split().tokenize(",", false, "${header.groups}")
+ .to("mock:split");
+
+ from("direct:b")
+ .split(bodyAs(String.class).tokenize(",", "${header.groups}", true))
+ .to("mock:split");
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/2f8b0190/camel-core/src/test/java/org/apache/camel/spring/processor/SpringSplitTokenizerGroupDynamicTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/spring/processor/SpringSplitTokenizerGroupDynamicTest.java b/camel-core/src/test/java/org/apache/camel/spring/processor/SpringSplitTokenizerGroupDynamicTest.java
new file mode 100644
index 0000000..d5cd66b
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/spring/processor/SpringSplitTokenizerGroupDynamicTest.java
@@ -0,0 +1,32 @@
+/**
+ * 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.spring.processor;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.processor.SplitTokenizerGroupDynamicTest;
+
+import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
+
+/**
+ * @version
+ */
+public class SpringSplitTokenizerGroupDynamicTest extends SplitTokenizerGroupDynamicTest {
+
+ protected CamelContext createCamelContext() throws Exception {
+ return createSpringCamelContext(this, "org/apache/camel/spring/processor/SpringSplitTokenizerGroupDynamicTest.xml");
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/2f8b0190/camel-core/src/test/resources/org/apache/camel/spring/processor/SpringSplitTokenizerGroupDynamicTest.xml
----------------------------------------------------------------------
diff --git a/camel-core/src/test/resources/org/apache/camel/spring/processor/SpringSplitTokenizerGroupDynamicTest.xml b/camel-core/src/test/resources/org/apache/camel/spring/processor/SpringSplitTokenizerGroupDynamicTest.xml
new file mode 100644
index 0000000..7744a14
--- /dev/null
+++ b/camel-core/src/test/resources/org/apache/camel/spring/processor/SpringSplitTokenizerGroupDynamicTest.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+ ">
+
+ <!-- START SNIPPET: example -->
+ <camelContext xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="direct:a"/>
+ <split>
+ <tokenize token="," group="${header.groups}"/>
+ <to uri="mock:split"/>
+ </split>
+ </route>
+ <route>
+ <from uri="direct:b"/>
+ <split>
+ <tokenize token="," group="${header.groups}" skipFirst="true"/>
+ <to uri="mock:split"/>
+ </split>
+ </route>
+ </camelContext>
+ <!-- END SNIPPET: example -->
+
+</beans>