This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new d3a492c6234a CAMEL-22894: Refactor `SimpleFunctionExpression`:
introduce function-factory dispatcher (part 1) (#23263)
d3a492c6234a is described below
commit d3a492c6234a26e63d40741caa37df51f82e345a
Author: Adriano Machado <[email protected]>
AuthorDate: Wed May 20 02:51:27 2026 -0400
CAMEL-22894: Refactor `SimpleFunctionExpression`: introduce
function-factory dispatcher (part 1) (#23263)
* CAMEL-22894: Deprecate SimpleLanguageFunctionFactory#createCode
The createCode(...) method exists solely to support csimple, which is
deprecated since 4.19 and slated for removal in 5.0. Mark the method
@Deprecated(since = "4.21") and make it a default returning null so
implementations that no longer care about csimple don't need to
override it. The three in-tree implementations (camel-attachments,
camel-base64, camel-jsoup) keep their existing overrides and pick up
the deprecation marker via inheritance.
This is the first step toward refactoring the dual-responsibility
SimpleFunctionExpression class.
rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
* CAMEL-22894: Centralize external-component function dispatch in
SimpleFunctionDispatcher
SimpleFunctionExpression had six near-identical methods plus six gating
predicate blocks dedicated to dispatching function strings to the three
SimpleLanguageFunctionFactory implementations shipped by external
components (camel-attachments, camel-base64, camel-jsoup). Move the
dispatch into a new SimpleFunctionDispatcher, which owns the list of
known component factories and their gating predicates and exposes
tryCreate(...) / tryCreateCode(...) entry points.
Behavior preserved exactly:
- Same factories consulted in the same order.
- Same gating predicates (so a function string belonging to a missing
component still surfaces the helpful "add this JAR" error via
ResolverHelper.resolveMandatoryBootstrapService).
- camel-jsoup remains excluded from the csimple createCode dispatch
(it has no csimple support and would throw).
Net: SimpleFunctionExpression shrinks by ~80 lines and adding a fourth
external factory is now a one-line edit in SimpleFunctionDispatcher
instead of a six-block change spread across SimpleFunctionExpression.
rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
* CAMEL-22894: Extract random, skip, collate, join into
SimpleLanguageFunctionFactory classes
Move four self-contained Simple functions out of SimpleFunctionExpression
into their own SimpleLanguageFunctionFactory implementations under
org.apache.camel.language.simple.functions, registered as built-ins on
SimpleFunctionDispatcher. The dispatcher consults built-ins before
external component factories, preserving today's priority.
Both createFunction (Simple) and createCode (csimple) are moved together
into each class, keeping the runtime and code-generation logic for the
same function side by side instead of ~2,000 lines apart in
SimpleFunctionExpression.
Behavior preserved: each factory short-circuits on its function prefix
and returns null on non-match, exactly mirroring the inline blocks they
replace. All Simple and CSimple tests continue to pass.
SimpleFunctionExpression shrinks by ~147 lines.
rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
* CAMEL-22894: Address review feedback on simple function extraction
- restore built-in function dispatch ordering relative to misc/math parsing
- move codeSplitSafe into SimpleFunctionHelper to decouple
JoinFunctionFactory from SimpleFunctionExpression
- align SkipFunctionFactory runtime parsing with createCode using beforeLast
- move random/skip/collate/join coverage into dedicated factory unit tests
rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
* CAMEL-22894: Route factory tests through full Simple language pipeline
`AbstractSimpleFunctionFactoryTestSupport.evaluate()` previously called
the factory directly, bypassing `SimpleFunctionExpression` and the
dispatcher entirely. The four factory tests therefore did not exercise
the dispatch ordering (built-ins before misc/math) that the review
flagged.
Route `evaluate()` through `context.resolveLanguage("simple")` so each
factory test exercises the full tokenizer -> parser -> dispatcher ->
factory chain. `createCode()` continues to call the factory directly
since there is no equivalent full pipeline for csimple.
The two error-message assertions in `RandomFunctionFactoryTest` are
updated to check `getCause().getMessage()`: the full pipeline wraps
the factory's `SimpleParserException` inside a
`SimpleIllegalSyntaxException` that appends location context.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
---
.../camel/spi/SimpleLanguageFunctionFactory.java | 14 +-
.../language/simple/SimpleFunctionDispatcher.java | 179 +++++++++++++++
.../language/simple/SimpleFunctionHelper.java | 142 ++++++++++++
.../simple/ast/SimpleFunctionExpression.java | 255 ++-------------------
.../simple/functions/CollateFunctionFactory.java | 59 +++++
.../simple/functions/JoinFunctionFactory.java | 107 +++++++++
.../simple/functions/RandomFunctionFactory.java | 77 +++++++
.../simple/functions/SkipFunctionFactory.java | 59 +++++
.../csimple/CSimpleExpressionParserTest.java | 23 +-
.../apache/camel/language/simple/SimpleTest.java | 194 ----------------
.../AbstractSimpleFunctionFactoryTestSupport.java | 45 ++++
.../functions/CollateFunctionFactoryTest.java | 128 +++++++++++
.../simple/functions/JoinFunctionFactoryTest.java | 64 ++++++
.../functions/RandomFunctionFactoryTest.java | 80 +++++++
.../simple/functions/SkipFunctionFactoryTest.java | 79 +++++++
15 files changed, 1047 insertions(+), 458 deletions(-)
diff --git
a/core/camel-api/src/main/java/org/apache/camel/spi/SimpleLanguageFunctionFactory.java
b/core/camel-api/src/main/java/org/apache/camel/spi/SimpleLanguageFunctionFactory.java
index 9532159c51a7..9667ccb3409f 100644
---
a/core/camel-api/src/main/java/org/apache/camel/spi/SimpleLanguageFunctionFactory.java
+++
b/core/camel-api/src/main/java/org/apache/camel/spi/SimpleLanguageFunctionFactory.java
@@ -49,12 +49,16 @@ public interface SimpleLanguageFunctionFactory {
/**
* Creates the Java source code that performs the function (for csimple).
*
- * @param camelContext the camel context
- * @param function the function
- * @param index index of the function in the literal input
- * @return the source code or <tt>null</tt> if not supported
by this factory.
+ * @param camelContext the camel context
+ * @param function the function
+ * @param index index of the function in the literal input
+ * @return the source code or <tt>null</tt> if not
supported by this factory.
+ * @deprecated will be removed in 5.0 along with csimple
*/
@Nullable
- String createCode(CamelContext camelContext, String function, int index);
+ @Deprecated(since = "4.21")
+ default String createCode(CamelContext camelContext, String function, int
index) {
+ return null;
+ }
}
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleFunctionDispatcher.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleFunctionDispatcher.java
new file mode 100644
index 000000000000..65057ecb8124
--- /dev/null
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleFunctionDispatcher.java
@@ -0,0 +1,179 @@
+/*
+ * 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.language.simple;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.functions.CollateFunctionFactory;
+import org.apache.camel.language.simple.functions.JoinFunctionFactory;
+import org.apache.camel.language.simple.functions.RandomFunctionFactory;
+import org.apache.camel.language.simple.functions.SkipFunctionFactory;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.apache.camel.support.ResolverHelper;
+
+import static
org.apache.camel.language.simple.ast.SimpleFunctionExpression.ifStartsWithReturnRemainder;
+
+/**
+ * Dispatches Simple/CSimple function lookup to built-in function factories
and to {@link SimpleLanguageFunctionFactory}
+ * implementations shipped by external Camel components (currently
camel-attachments, camel-base64, camel-jsoup).
+ * <p>
+ * Each entry carries a gate that decides whether its factory is consulted for
a given function string; gates mirror the
+ * inline checks that previously lived in {@code SimpleFunctionExpression}, so
a function belonging to a missing
+ * component still surfaces the "add the JAR to your classpath" error from
+ * {@link ResolverHelper#resolveMandatoryBootstrapService}. Factory resolution
is cached by the bootstrap factory
+ * finder, so repeated dispatch is cheap.
+ */
+public final class SimpleFunctionDispatcher {
+
+ /**
+ * Built-in factories shipped by camel-core-languages itself. Iterated
before {@link #EXPRESSION_ENTRIES}, matching
+ * the original priority of these functions inside {@code
SimpleFunctionExpression}. Each factory returns
+ * {@code null} for inputs it does not recognise, so no gating predicate
is needed.
+ */
+ private static final List<SimpleLanguageFunctionFactory> BUILT_INS =
List.of(
+ new RandomFunctionFactory(),
+ new SkipFunctionFactory(),
+ new CollateFunctionFactory(),
+ new JoinFunctionFactory());
+
+ private static final List<Entry> EXPRESSION_ENTRIES = List.of(
+ new Entry("camel-attachments",
SimpleFunctionDispatcher::isAttachmentFunction),
+ new Entry("camel-base64",
SimpleFunctionDispatcher::isBase64Function),
+ new Entry("camel-jsoup",
SimpleFunctionDispatcher::isHtmlFunction));
+
+ /**
+ * Code-generation entries exclude camel-jsoup deliberately: it has no
csimple support and its {@code createCode}
+ * throws.
+ */
+ private static final List<Entry> CODE_ENTRIES = List.of(
+ new Entry("camel-attachments",
SimpleFunctionDispatcher::isAttachmentFunction),
+ new Entry("camel-base64",
SimpleFunctionDispatcher::isBase64Function));
+
+ private SimpleFunctionDispatcher() {
+ }
+
+ public static Expression tryCreate(CamelContext camelContext, String
function, int index) {
+ Expression answer = tryCreateBuiltIn(camelContext, function, index);
+ if (answer != null) {
+ return answer;
+ }
+ return tryCreateExternal(camelContext, function, index);
+ }
+
+ public static Expression tryCreateBuiltIn(CamelContext camelContext,
String function, int index) {
+ for (SimpleLanguageFunctionFactory factory : BUILT_INS) {
+ Expression answer = factory.createFunction(camelContext, function,
index);
+ if (answer != null) {
+ return answer;
+ }
+ }
+ return null;
+ }
+
+ public static Expression tryCreateExternal(CamelContext camelContext,
String function, int index) {
+ for (Entry entry : EXPRESSION_ENTRIES) {
+ if (!entry.claims.test(function)) {
+ continue;
+ }
+ SimpleLanguageFunctionFactory factory = resolve(camelContext,
entry.jarName);
+ Expression answer = factory.createFunction(camelContext, function,
index);
+ if (answer != null) {
+ return answer;
+ }
+ }
+ return null;
+ }
+
+ public static String tryCreateCode(CamelContext camelContext, String
function, int index) {
+ String code = tryCreateCodeBuiltIn(camelContext, function, index);
+ if (code != null) {
+ return code;
+ }
+ return tryCreateCodeExternal(camelContext, function, index);
+ }
+
+ public static String tryCreateCodeBuiltIn(CamelContext camelContext,
String function, int index) {
+ for (SimpleLanguageFunctionFactory factory : BUILT_INS) {
+ @SuppressWarnings("deprecation")
+ String code = factory.createCode(camelContext, function, index);
+ if (code != null) {
+ return code;
+ }
+ }
+ return null;
+ }
+
+ public static String tryCreateCodeExternal(CamelContext camelContext,
String function, int index) {
+ for (Entry entry : CODE_ENTRIES) {
+ if (!entry.claims.test(function)) {
+ continue;
+ }
+ SimpleLanguageFunctionFactory factory = resolve(camelContext,
entry.jarName);
+ @SuppressWarnings("deprecation")
+ String code = factory.createCode(camelContext, function, index);
+ if (code != null) {
+ return code;
+ }
+ }
+ return null;
+ }
+
+ private static SimpleLanguageFunctionFactory resolve(CamelContext
camelContext, String jarName) {
+ return ResolverHelper.resolveMandatoryBootstrapService(
+ camelContext,
+ SimpleLanguageFunctionFactory.FACTORY + "/" + jarName,
+ SimpleLanguageFunctionFactory.class,
+ jarName);
+ }
+
+ private static boolean isAttachmentFunction(String function) {
+ return "attachments".equals(function)
+ || "clearAttachments".equals(function)
+ || ifStartsWithReturnRemainder("setAttachment", function) !=
null
+ || ifStartsWithReturnRemainder("attachment", function) != null;
+ }
+
+ private static boolean isBase64Function(String function) {
+ return "base64Encode".equals(function)
+ || "base64Decode".equals(function)
+ || ifStartsWithReturnRemainder("base64Encode", function) !=
null
+ || ifStartsWithReturnRemainder("base64Decode", function) !=
null;
+ }
+
+ private static boolean isHtmlFunction(String function) {
+ return "htmlClean".equals(function)
+ || "htmlParse".equals(function)
+ || "htmlDecode".equals(function)
+ || ifStartsWithReturnRemainder("htmlClean", function) != null
+ || ifStartsWithReturnRemainder("htmlParse", function) != null
+ || ifStartsWithReturnRemainder("htmlDecode", function) != null;
+ }
+
+ private static final class Entry {
+
+ private final String jarName;
+ private final Predicate<String> claims;
+
+ private Entry(String jarName, Predicate<String> claims) {
+ this.jarName = jarName;
+ this.claims = claims;
+ }
+ }
+}
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleFunctionHelper.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleFunctionHelper.java
new file mode 100644
index 000000000000..d6ae1b132dce
--- /dev/null
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleFunctionHelper.java
@@ -0,0 +1,142 @@
+/*
+ * 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.language.simple;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public final class SimpleFunctionHelper {
+
+ private SimpleFunctionHelper() {
+ }
+
+ public static String[] codeSplitSafe(String input, char separator, boolean
trim, boolean keepQuotes) {
+ if (input == null) {
+ return null;
+ }
+
+ if (input.indexOf(separator) == -1) {
+ if (input.length() > 1) {
+ char ch = input.charAt(0);
+ char ch2 = input.charAt(input.length() - 1);
+ boolean singleQuoted = ch == '\'' && ch2 == '\'';
+ boolean doubleQuoted = ch == '"' && ch2 == '"';
+ if (!keepQuotes && (singleQuoted || doubleQuoted)) {
+ input = input.substring(1, input.length() - 1);
+ // do not trim quoted text
+ } else if (trim) {
+ input = input.trim();
+ }
+ }
+ return new String[] { input };
+ }
+
+ List<String> answer = new ArrayList<>();
+ StringBuilder sb = new StringBuilder(256);
+
+ int codeLevel = 0;
+ boolean singleQuoted = false;
+ boolean doubleQuoted = false;
+ boolean separating = false;
+
+ for (int i = 0; i < input.length(); i++) {
+ char ch = input.charAt(i);
+ char prev = i > 0 ? input.charAt(i - 1) : 0;
+ boolean isQuoting = singleQuoted || doubleQuoted;
+ boolean last = i == input.length() - 1;
+
+ if (input.indexOf(BaseSimpleParser.CODE_START, i) == i) {
+ codeLevel++;
+ sb.append(BaseSimpleParser.CODE_START);
+ i = i + BaseSimpleParser.CODE_START.length() - 1;
+ continue;
+ } else if (input.indexOf(BaseSimpleParser.CODE_END, i) == i) {
+ codeLevel--;
+ sb.append(BaseSimpleParser.CODE_END);
+ i = i + BaseSimpleParser.CODE_END.length() - 1;
+ continue;
+ }
+ if (codeLevel > 0) {
+ sb.append(ch);
+ continue;
+ }
+
+ if (!doubleQuoted && ch == '\'') {
+ if (!singleQuoted) {
+ singleQuoted = true;
+ if (keepQuotes) {
+ sb.append(ch);
+ }
+ continue;
+ } else if (prev != '\\') {
+ singleQuoted = false;
+ if (keepQuotes) {
+ sb.append(ch);
+ }
+ continue;
+ }
+ } else if (!singleQuoted && ch == '"') {
+ if (!doubleQuoted) {
+ doubleQuoted = true;
+ if (keepQuotes) {
+ sb.append(ch);
+ }
+ continue;
+ } else if (prev != '\\') {
+ doubleQuoted = false;
+ if (keepQuotes) {
+ sb.append(ch);
+ }
+ continue;
+ }
+ }
+
+ if (isQuoting) {
+ sb.append(ch);
+ continue;
+ }
+
+ if (ch == separator) {
+ if (separating) {
+ continue;
+ }
+ String s = sb.toString();
+ if (trim) {
+ s = s.trim();
+ }
+ answer.add(s);
+ sb.setLength(0);
+ separating = true;
+ continue;
+ } else if (separating) {
+ separating = false;
+ }
+
+ sb.append(ch);
+
+ if (last) {
+ String s = sb.toString();
+ if (trim) {
+ s = s.trim();
+ }
+ answer.add(s);
+ }
+ }
+
+ return answer.toArray(new String[0]);
+ }
+}
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
index 825478e0fd76..843691c5a6b3 100644
---
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
@@ -29,13 +29,12 @@ import org.apache.camel.Expression;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.language.simple.BaseSimpleParser;
import org.apache.camel.language.simple.SimpleExpressionBuilder;
+import org.apache.camel.language.simple.SimpleFunctionDispatcher;
import org.apache.camel.language.simple.SimplePredicateParser;
import org.apache.camel.language.simple.types.SimpleParserException;
import org.apache.camel.language.simple.types.SimpleToken;
import org.apache.camel.spi.Language;
-import org.apache.camel.spi.SimpleLanguageFunctionFactory;
import org.apache.camel.support.PluginHelper;
-import org.apache.camel.support.ResolverHelper;
import org.apache.camel.support.builder.ExpressionBuilder;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.OgnlHelper;
@@ -391,6 +390,10 @@ public class SimpleFunctionExpression extends
LiteralExpression {
}
// miscellaneous functions
+ Expression builtIn =
SimpleFunctionDispatcher.tryCreateBuiltIn(camelContext, function,
token.getIndex());
+ if (builtIn != null) {
+ return builtIn;
+ }
Expression misc = createSimpleExpressionMisc(function);
if (misc != null) {
return misc;
@@ -401,33 +404,10 @@ public class SimpleFunctionExpression extends
LiteralExpression {
return math;
}
- // attachments
- if ("attachments".equals(function) ||
"clearAttachments".equals(function)
- || ifStartsWithReturnRemainder("setAttachment", function) !=
null
- || ifStartsWithReturnRemainder("attachment", function) !=
null) {
- Expression exp = createSimpleAttachments(camelContext, function);
- if (exp != null) {
- return exp;
- }
- }
- // base64
- if ("base64Encode".equals(function) || "base64Decode".equals(function)
- || ifStartsWithReturnRemainder("base64Encode", function) !=
null
- || ifStartsWithReturnRemainder("base64Decode", function) !=
null) {
- Expression exp = createSimpleBase64(camelContext, function);
- if (exp != null) {
- return exp;
- }
- }
- // html
- if ("htmlClean".equals(function) || "htmlParse".equals(function) ||
"htmlDecode".equals(function)
- || ifStartsWithReturnRemainder("htmlClean", function) != null
- || ifStartsWithReturnRemainder("htmlParse", function) != null
- || ifStartsWithReturnRemainder("htmlDecode", function) !=
null) {
- Expression exp = createSimpleHtml(camelContext, function);
- if (exp != null) {
- return exp;
- }
+ // functions from external components (attachments, base64, html, ...)
+ Expression external =
SimpleFunctionDispatcher.tryCreateExternal(camelContext, function,
token.getIndex());
+ if (external != null) {
+ return external;
}
// it may be a custom function
@@ -452,33 +432,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
}
}
- private Expression createSimpleAttachments(CamelContext camelContext,
String function) {
- SimpleLanguageFunctionFactory factory =
ResolverHelper.resolveMandatoryBootstrapService(
- camelContext,
- SimpleLanguageFunctionFactory.FACTORY + "/camel-attachments",
- SimpleLanguageFunctionFactory.class,
- "camel-attachments");
- return factory.createFunction(camelContext, function,
token.getIndex());
- }
-
- private Expression createSimpleBase64(CamelContext camelContext, String
function) {
- SimpleLanguageFunctionFactory factory =
ResolverHelper.resolveMandatoryBootstrapService(
- camelContext,
- SimpleLanguageFunctionFactory.FACTORY + "/camel-base64",
- SimpleLanguageFunctionFactory.class,
- "camel-base64");
- return factory.createFunction(camelContext, function,
token.getIndex());
- }
-
- private Expression createSimpleHtml(CamelContext camelContext, String
function) {
- SimpleLanguageFunctionFactory factory =
ResolverHelper.resolveMandatoryBootstrapService(
- camelContext,
- SimpleLanguageFunctionFactory.FACTORY + "/camel-jsoup",
- SimpleLanguageFunctionFactory.class,
- "camel-jsoup");
- return factory.createFunction(camelContext, function,
token.getIndex());
- }
-
private Expression createSimpleExpressionMessage(CamelContext
camelContext, String function, boolean strict) {
// messageAs
String remainder = ifStartsWithReturnRemainder("messageAs(", function);
@@ -1115,25 +1068,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
return SimpleExpressionBuilder.containsExpression(exp, pattern);
}
- // random function
- remainder = ifStartsWithReturnRemainder("random(", function);
- if (remainder != null) {
- String values = StringHelper.beforeLast(remainder, ")");
- if (values == null || ObjectHelper.isEmpty(values)) {
- throw new SimpleParserException(
- "Valid syntax: ${random(min,max)} or ${random(max)}
was: " + function, token.getIndex());
- }
- if (values.contains(",")) {
- String[] tokens = values.split(",", 3);
- if (tokens.length > 2) {
- throw new SimpleParserException(
- "Valid syntax: ${random(min,max)} or
${random(max)} was: " + function, token.getIndex());
- }
- return
SimpleExpressionBuilder.randomExpression(tokens[0].trim(), tokens[1].trim());
- } else {
- return SimpleExpressionBuilder.randomExpression("0",
values.trim());
- }
- }
// range function
remainder = ifStartsWithReturnRemainder("range(", function);
if (remainder != null) {
@@ -1190,54 +1124,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
}
return SimpleExpressionBuilder.shuffleExpression(tokens);
}
- // skip function
- remainder = ifStartsWithReturnRemainder("skip(", function);
- if (remainder != null) {
- String values = StringHelper.before(remainder, ")");
- if (values == null || ObjectHelper.isEmpty(values)) {
- throw new SimpleParserException("Valid syntax: ${skip(number)}
was: " + function, token.getIndex());
- }
- String exp = "${body}";
- return SimpleExpressionBuilder.skipExpression(exp, values.trim());
- }
-
- // collate function
- remainder = ifStartsWithReturnRemainder("collate(", function);
- if (remainder != null) {
- String values = StringHelper.beforeLast(remainder, ")");
- if (values == null || ObjectHelper.isEmpty(values)) {
- throw new SimpleParserException("Valid syntax:
${collate(group)} was: " + function, token.getIndex());
- }
- String exp = "${body}";
- return SimpleExpressionBuilder.collateExpression(exp,
values.trim());
- }
-
- // join function
- remainder = ifStartsWithReturnRemainder("join(", function);
- if (remainder != null) {
- String values = StringHelper.beforeLast(remainder, ")");
- String separator = ",";
- String prefix = null;
- String exp = "${body}";
- if (ObjectHelper.isNotEmpty(values)) {
- String[] tokens = StringQuoteHelper.splitSafeQuote(values,
',', false);
- if (tokens.length > 3) {
- throw new SimpleParserException(
- "Valid syntax:
${join(separator,prefix,expression)} was: " + function, token.getIndex());
- }
- if (tokens.length == 3) {
- separator = tokens[0];
- prefix = tokens[1];
- exp = tokens[2];
- } else if (tokens.length == 2) {
- separator = tokens[0];
- prefix = tokens[1];
- } else {
- separator = tokens[0];
- }
- }
- return SimpleExpressionBuilder.joinExpression(exp, separator,
prefix);
- }
// split function
remainder = ifStartsWithReturnRemainder("split(", function);
if (remainder != null) {
@@ -2153,6 +2039,10 @@ public class SimpleFunctionExpression extends
LiteralExpression {
}
// miscellaneous functions
+ String builtIn =
SimpleFunctionDispatcher.tryCreateCodeBuiltIn(camelContext, function,
token.getIndex());
+ if (builtIn != null) {
+ return builtIn;
+ }
String misc = createCodeExpressionMisc(camelContext, function);
if (misc != null) {
return misc;
@@ -2163,23 +2053,10 @@ public class SimpleFunctionExpression extends
LiteralExpression {
return math;
}
- // attachments
- if ("attachments".equals(function) ||
"clearAttachments".equals(function)
- || ifStartsWithReturnRemainder("setAttachment", function) !=
null
- || ifStartsWithReturnRemainder("attachment", function) !=
null) {
- String code = createCodeAttachments(camelContext, function);
- if (code != null) {
- return code;
- }
- }
- // base64
- if ("base64Encode".equals(function) || "base64Decode".equals(function)
- || ifStartsWithReturnRemainder("base64Encode", function) !=
null
- || ifStartsWithReturnRemainder("base64Decode", function) !=
null) {
- String code = createCodeBase64(camelContext, function);
- if (code != null) {
- return code;
- }
+ // code from external components (attachments, base64, ...)
+ String external =
SimpleFunctionDispatcher.tryCreateCodeExternal(camelContext, function,
token.getIndex());
+ if (external != null) {
+ return external;
}
throw new SimpleParserException("Unknown function: " + function,
token.getIndex());
@@ -2791,24 +2668,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
throw new SimpleParserException("Unknown file language syntax: " +
remainder, token.getIndex());
}
- private String createCodeAttachments(CamelContext camelContext, String
function) {
- SimpleLanguageFunctionFactory factory =
ResolverHelper.resolveMandatoryBootstrapService(
- camelContext,
- SimpleLanguageFunctionFactory.FACTORY + "/camel-attachments",
- SimpleLanguageFunctionFactory.class,
- "camel-attachments");
- return factory.createCode(camelContext, function, token.getIndex());
- }
-
- private String createCodeBase64(CamelContext camelContext, String
function) {
- SimpleLanguageFunctionFactory factory =
ResolverHelper.resolveMandatoryBootstrapService(
- camelContext,
- SimpleLanguageFunctionFactory.FACTORY + "/camel-base64",
- SimpleLanguageFunctionFactory.class,
- "camel-base64");
- return factory.createCode(camelContext, function, token.getIndex());
- }
-
private String createCodeExpressionMisc(CamelContext camelContext, String
function) {
String remainder;
@@ -3123,27 +2982,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
return "Object value = " + exp + ";\n return
containsIgnoreCase(exchange, value, " + pattern + ");";
}
- // random function
- remainder = ifStartsWithReturnRemainder("random(", function);
- if (remainder != null) {
- String values = StringHelper.beforeLast(remainder, ")");
- if (values == null || ObjectHelper.isEmpty(values)) {
- throw new SimpleParserException(
- "Valid syntax: ${random(min,max)} or ${random(max)}
was: " + function, token.getIndex());
- }
- if (values.contains(",")) {
- String before = StringHelper.before(remainder, ",");
- before = before.trim();
- String after = StringHelper.after(remainder, ",");
- after = after.trim();
- if (after.endsWith(")")) {
- after = after.substring(0, after.length() - 1);
- }
- return "random(exchange, " + before + ", " + after + ")";
- } else {
- return "random(exchange, 0, " + values.trim() + ")";
- }
- }
remainder = ifStartsWithReturnRemainder("range(", function);
if (remainder != null) {
String values = StringHelper.beforeLast(remainder, ")");
@@ -3260,16 +3098,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
return "shuffle(exchange, " + p + ")";
}
- // skip function
- remainder = ifStartsWithReturnRemainder("skip(", function);
- if (remainder != null) {
- String values = StringHelper.beforeLast(remainder, ")");
- if (values == null || ObjectHelper.isEmpty(values)) {
- throw new SimpleParserException("Valid syntax: ${skip(number)}
was: " + function, token.getIndex());
- }
- return "skip(exchange, " + values.trim() + ")";
- }
-
// pad function
remainder = ifStartsWithReturnRemainder("pad(", function);
if (remainder != null) {
@@ -3845,16 +3673,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
return "Object o = " + exp + ";\n return
normalizeWhitespace(exchange, o);";
}
- // collate function
- remainder = ifStartsWithReturnRemainder("collate(", function);
- if (remainder != null) {
- String values = StringHelper.beforeLast(remainder, ")");
- if (values == null || ObjectHelper.isEmpty(values)) {
- throw new SimpleParserException("Valid syntax:
${collate(group)} was: " + function, token.getIndex());
- }
- return "collate(exchange, " + values.trim() + ")";
- }
-
// messageHistory function
remainder = ifStartsWithReturnRemainder("messageHistory", function);
if (remainder != null) {
@@ -3870,45 +3688,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
return "messageHistory(exchange, true)";
}
- // join function
- remainder = ifStartsWithReturnRemainder("join(", function);
- if (remainder != null) {
- String values = StringHelper.beforeLast(remainder, ")");
- String separator = "\",\"";
- String prefix = null;
- String exp = "body";
- if (ObjectHelper.isNotEmpty(values)) {
- String[] tokens = codeSplitSafe(values, ',', true, true);
- if (tokens.length > 3) {
- throw new SimpleParserException(
- "Valid syntax:
${join(separator,prefix,expression)} was: " + function, token.getIndex());
- }
- // single quotes should be double quotes
- for (int i = 0; i < tokens.length; i++) {
- String s = tokens[i];
- if (StringHelper.isSingleQuoted(s)) {
- s = StringHelper.removeLeadingAndEndingQuotes(s);
- s = StringQuoteHelper.doubleQuote(s);
- tokens[i] = s;
- } else if (i < 2 && !StringHelper.isDoubleQuoted(s)) {
- s = StringQuoteHelper.doubleQuote(s);
- tokens[i] = s;
- }
- }
- if (tokens.length == 3) {
- separator = tokens[0];
- prefix = tokens[1];
- exp = tokens[2];
- } else if (tokens.length == 2) {
- separator = tokens[0];
- prefix = tokens[1];
- } else {
- separator = tokens[0];
- }
- }
- return "var val = " + exp + ";\n return join(exchange, val,
" + separator + ", " + prefix + ");";
- }
-
// empty function
remainder = ifStartsWithReturnRemainder("empty(", function);
if (remainder != null) {
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/CollateFunctionFactory.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/CollateFunctionFactory.java
new file mode 100644
index 000000000000..c2a3a43c5894
--- /dev/null
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/CollateFunctionFactory.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.language.simple.functions;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleExpressionBuilder;
+import org.apache.camel.language.simple.types.SimpleParserException;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.StringHelper;
+
+import static
org.apache.camel.language.simple.ast.SimpleFunctionExpression.ifStartsWithReturnRemainder;
+
+/**
+ * Built-in Simple function: {@code ${collate(group)}}.
+ */
+public final class CollateFunctionFactory implements
SimpleLanguageFunctionFactory {
+
+ @Override
+ public Expression createFunction(CamelContext camelContext, String
function, int index) {
+ String remainder = ifStartsWithReturnRemainder("collate(", function);
+ if (remainder == null) {
+ return null;
+ }
+ String values = StringHelper.beforeLast(remainder, ")");
+ if (values == null || ObjectHelper.isEmpty(values)) {
+ throw new SimpleParserException("Valid syntax: ${collate(group)}
was: " + function, index);
+ }
+ return SimpleExpressionBuilder.collateExpression("${body}",
values.trim());
+ }
+
+ @Override
+ public String createCode(CamelContext camelContext, String function, int
index) {
+ String remainder = ifStartsWithReturnRemainder("collate(", function);
+ if (remainder == null) {
+ return null;
+ }
+ String values = StringHelper.beforeLast(remainder, ")");
+ if (values == null || ObjectHelper.isEmpty(values)) {
+ throw new SimpleParserException("Valid syntax: ${collate(group)}
was: " + function, index);
+ }
+ return "collate(exchange, " + values.trim() + ")";
+ }
+}
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/JoinFunctionFactory.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/JoinFunctionFactory.java
new file mode 100644
index 000000000000..ea124ccdd6d2
--- /dev/null
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/JoinFunctionFactory.java
@@ -0,0 +1,107 @@
+/*
+ * 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.language.simple.functions;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleExpressionBuilder;
+import org.apache.camel.language.simple.SimpleFunctionHelper;
+import org.apache.camel.language.simple.types.SimpleParserException;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.StringHelper;
+import org.apache.camel.util.StringQuoteHelper;
+
+import static
org.apache.camel.language.simple.ast.SimpleFunctionExpression.ifStartsWithReturnRemainder;
+
+/**
+ * Built-in Simple function: {@code ${join()}} / {@code ${join(separator)}} /
{@code ${join(separator,prefix)}} /
+ * {@code ${join(separator,prefix,expression)}}.
+ */
+public final class JoinFunctionFactory implements
SimpleLanguageFunctionFactory {
+
+ @Override
+ public Expression createFunction(CamelContext camelContext, String
function, int index) {
+ String remainder = ifStartsWithReturnRemainder("join(", function);
+ if (remainder == null) {
+ return null;
+ }
+ String values = StringHelper.beforeLast(remainder, ")");
+ String separator = ",";
+ String prefix = null;
+ String exp = "${body}";
+ if (ObjectHelper.isNotEmpty(values)) {
+ String[] tokens = StringQuoteHelper.splitSafeQuote(values, ',',
false);
+ if (tokens.length > 3) {
+ throw new SimpleParserException(
+ "Valid syntax: ${join(separator,prefix,expression)}
was: " + function, index);
+ }
+ if (tokens.length == 3) {
+ separator = tokens[0];
+ prefix = tokens[1];
+ exp = tokens[2];
+ } else if (tokens.length == 2) {
+ separator = tokens[0];
+ prefix = tokens[1];
+ } else {
+ separator = tokens[0];
+ }
+ }
+ return SimpleExpressionBuilder.joinExpression(exp, separator, prefix);
+ }
+
+ @Override
+ public String createCode(CamelContext camelContext, String function, int
index) {
+ String remainder = ifStartsWithReturnRemainder("join(", function);
+ if (remainder == null) {
+ return null;
+ }
+ String values = StringHelper.beforeLast(remainder, ")");
+ String separator = "\",\"";
+ String prefix = null;
+ String exp = "body";
+ if (ObjectHelper.isNotEmpty(values)) {
+ String[] tokens = SimpleFunctionHelper.codeSplitSafe(values, ',',
true, true);
+ if (tokens.length > 3) {
+ throw new SimpleParserException(
+ "Valid syntax: ${join(separator,prefix,expression)}
was: " + function, index);
+ }
+ for (int i = 0; i < tokens.length; i++) {
+ String s = tokens[i];
+ if (StringHelper.isSingleQuoted(s)) {
+ s = StringHelper.removeLeadingAndEndingQuotes(s);
+ s = StringQuoteHelper.doubleQuote(s);
+ tokens[i] = s;
+ } else if (i < 2 && !StringHelper.isDoubleQuoted(s)) {
+ s = StringQuoteHelper.doubleQuote(s);
+ tokens[i] = s;
+ }
+ }
+ if (tokens.length == 3) {
+ separator = tokens[0];
+ prefix = tokens[1];
+ exp = tokens[2];
+ } else if (tokens.length == 2) {
+ separator = tokens[0];
+ prefix = tokens[1];
+ } else {
+ separator = tokens[0];
+ }
+ }
+ return "var val = " + exp + ";\n return join(exchange, val, " +
separator + ", " + prefix + ");";
+ }
+}
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/RandomFunctionFactory.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/RandomFunctionFactory.java
new file mode 100644
index 000000000000..81e00c9aa521
--- /dev/null
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/RandomFunctionFactory.java
@@ -0,0 +1,77 @@
+/*
+ * 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.language.simple.functions;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleExpressionBuilder;
+import org.apache.camel.language.simple.types.SimpleParserException;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.StringHelper;
+
+import static
org.apache.camel.language.simple.ast.SimpleFunctionExpression.ifStartsWithReturnRemainder;
+
+/**
+ * Built-in Simple function: {@code ${random(max)}} / {@code
${random(min,max)}}.
+ */
+public final class RandomFunctionFactory implements
SimpleLanguageFunctionFactory {
+
+ @Override
+ public Expression createFunction(CamelContext camelContext, String
function, int index) {
+ String remainder = ifStartsWithReturnRemainder("random(", function);
+ if (remainder == null) {
+ return null;
+ }
+ String values = StringHelper.beforeLast(remainder, ")");
+ if (values == null || ObjectHelper.isEmpty(values)) {
+ throw new SimpleParserException(
+ "Valid syntax: ${random(min,max)} or ${random(max)} was: "
+ function, index);
+ }
+ if (values.contains(",")) {
+ String[] tokens = values.split(",", 3);
+ if (tokens.length > 2) {
+ throw new SimpleParserException(
+ "Valid syntax: ${random(min,max)} or ${random(max)}
was: " + function, index);
+ }
+ return SimpleExpressionBuilder.randomExpression(tokens[0].trim(),
tokens[1].trim());
+ }
+ return SimpleExpressionBuilder.randomExpression("0", values.trim());
+ }
+
+ @Override
+ public String createCode(CamelContext camelContext, String function, int
index) {
+ String remainder = ifStartsWithReturnRemainder("random(", function);
+ if (remainder == null) {
+ return null;
+ }
+ String values = StringHelper.beforeLast(remainder, ")");
+ if (values == null || ObjectHelper.isEmpty(values)) {
+ throw new SimpleParserException(
+ "Valid syntax: ${random(min,max)} or ${random(max)} was: "
+ function, index);
+ }
+ if (values.contains(",")) {
+ String before = StringHelper.before(remainder, ",").trim();
+ String after = StringHelper.after(remainder, ",").trim();
+ if (after.endsWith(")")) {
+ after = after.substring(0, after.length() - 1);
+ }
+ return "random(exchange, " + before + ", " + after + ")";
+ }
+ return "random(exchange, 0, " + values.trim() + ")";
+ }
+}
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/SkipFunctionFactory.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/SkipFunctionFactory.java
new file mode 100644
index 000000000000..e5fb4073fcd8
--- /dev/null
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/SkipFunctionFactory.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.language.simple.functions;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleExpressionBuilder;
+import org.apache.camel.language.simple.types.SimpleParserException;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.StringHelper;
+
+import static
org.apache.camel.language.simple.ast.SimpleFunctionExpression.ifStartsWithReturnRemainder;
+
+/**
+ * Built-in Simple function: {@code ${skip(number)}}.
+ */
+public final class SkipFunctionFactory implements
SimpleLanguageFunctionFactory {
+
+ @Override
+ public Expression createFunction(CamelContext camelContext, String
function, int index) {
+ String remainder = ifStartsWithReturnRemainder("skip(", function);
+ if (remainder == null) {
+ return null;
+ }
+ String values = StringHelper.beforeLast(remainder, ")");
+ if (values == null || ObjectHelper.isEmpty(values)) {
+ throw new SimpleParserException("Valid syntax: ${skip(number)}
was: " + function, index);
+ }
+ return SimpleExpressionBuilder.skipExpression("${body}",
values.trim());
+ }
+
+ @Override
+ public String createCode(CamelContext camelContext, String function, int
index) {
+ String remainder = ifStartsWithReturnRemainder("skip(", function);
+ if (remainder == null) {
+ return null;
+ }
+ String values = StringHelper.beforeLast(remainder, ")");
+ if (values == null || ObjectHelper.isEmpty(values)) {
+ throw new SimpleParserException("Valid syntax: ${skip(number)}
was: " + function, index);
+ }
+ return "skip(exchange, " + values.trim() + ")";
+ }
+}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/csimple/CSimpleExpressionParserTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/csimple/CSimpleExpressionParserTest.java
index 3997120b316b..2d5dbaf53b53 100644
---
a/core/camel-core/src/test/java/org/apache/camel/language/csimple/CSimpleExpressionParserTest.java
+++
b/core/camel-core/src/test/java/org/apache/camel/language/csimple/CSimpleExpressionParserTest.java
@@ -46,29 +46,10 @@ public class CSimpleExpressionParserTest {
}
@Test
- public void testMisc() {
+ public void testMessageHistory() {
CSimpleExpressionParser parser = new CSimpleExpressionParser();
- String code = parser.parseExpression("${random(10)}");
- Assertions.assertEquals("random(exchange, 0, 10)", code);
- code = parser.parseExpression("${random(10, 20)}");
- Assertions.assertEquals("random(exchange, 10, 20)", code);
- code = parser.parseExpression("${random(10, ${header.max})}");
- Assertions.assertEquals("random(exchange, 10, header(message,
\"max\"))", code);
- code = parser.parseExpression("${random(${header.min},
${header.max})}");
- Assertions.assertEquals("random(exchange, header(message, \"min\"),
header(message, \"max\"))", code);
-
- code = parser.parseExpression("${skip(10)}");
- Assertions.assertEquals("skip(exchange, 10)", code);
- code = parser.parseExpression("${skip(${header.max})}");
- Assertions.assertEquals("skip(exchange, header(message, \"max\"))",
code);
-
- code = parser.parseExpression("${collate(10)}");
- Assertions.assertEquals("collate(exchange, 10)", code);
- code = parser.parseExpression("${collate(${header.max})}");
- Assertions.assertEquals("collate(exchange, header(message, \"max\"))",
code);
-
- code = parser.parseExpression("${messageHistory}");
+ String code = parser.parseExpression("${messageHistory}");
Assertions.assertEquals("messageHistory(exchange, true)", code);
code = parser.parseExpression("${messageHistory(false)}");
Assertions.assertEquals("messageHistory(exchange, false)", code);
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
index 1bd1a04f4faa..7255773cf3f2 100644
---
a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
+++
b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
@@ -26,7 +26,6 @@ import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -1959,199 +1958,6 @@ public class SimpleTest extends LanguageTestSupport {
assertPredicate("${body} regex
'^(tel:\\+)(974)(44)(\\d+)|^(974)(44)(\\d+)'", false);
}
- @Test
- public void testCollateEven() {
- List<Object> data = new ArrayList<>();
- data.add("A");
- data.add("B");
- data.add("C");
- data.add("D");
- data.add("E");
- data.add("F");
- exchange.getIn().setBody(data);
-
- Iterator it = (Iterator) evaluateExpression("${collate(3)}", null);
- List chunk = (List) it.next();
- List chunk2 = (List) it.next();
- assertFalse(it.hasNext());
-
- assertEquals(3, chunk.size());
- assertEquals(3, chunk2.size());
-
- assertEquals("A", chunk.get(0));
- assertEquals("B", chunk.get(1));
- assertEquals("C", chunk.get(2));
- assertEquals("D", chunk2.get(0));
- assertEquals("E", chunk2.get(1));
- assertEquals("F", chunk2.get(2));
- }
-
- @Test
- public void testCollateOdd() {
- List<Object> data = new ArrayList<>();
- data.add("A");
- data.add("B");
- data.add("C");
- data.add("D");
- data.add("E");
- data.add("F");
- data.add("G");
- exchange.getIn().setBody(data);
-
- Iterator it = (Iterator) evaluateExpression("${collate(3)}", null);
- List chunk = (List) it.next();
- List chunk2 = (List) it.next();
- List chunk3 = (List) it.next();
- assertFalse(it.hasNext());
-
- assertEquals(3, chunk.size());
- assertEquals(3, chunk2.size());
- assertEquals(1, chunk3.size());
-
- assertEquals("A", chunk.get(0));
- assertEquals("B", chunk.get(1));
- assertEquals("C", chunk.get(2));
- assertEquals("D", chunk2.get(0));
- assertEquals("E", chunk2.get(1));
- assertEquals("F", chunk2.get(2));
- assertEquals("G", chunk3.get(0));
- }
-
- @Test
- public void testCollateDynamic() {
- List<Object> data = new ArrayList<>();
- data.add("A");
- data.add("B");
- data.add("C");
- data.add("D");
- data.add("E");
- data.add("F");
- data.add("G");
- exchange.getIn().setBody(data);
-
- exchange.getIn().setHeader("num", 3);
-
- Iterator it = (Iterator)
evaluateExpression("${collate(${header.num})}", null);
- List chunk = (List) it.next();
- List chunk2 = (List) it.next();
- List chunk3 = (List) it.next();
- assertFalse(it.hasNext());
-
- assertEquals(3, chunk.size());
- assertEquals(3, chunk2.size());
- assertEquals(1, chunk3.size());
-
- assertEquals("A", chunk.get(0));
- assertEquals("B", chunk.get(1));
- assertEquals("C", chunk.get(2));
- assertEquals("D", chunk2.get(0));
- assertEquals("E", chunk2.get(1));
- assertEquals("F", chunk2.get(2));
- assertEquals("G", chunk3.get(0));
- }
-
- @Test
- public void testSkip() {
- List<Object> data = new ArrayList<>();
- data.add("A");
- data.add("B");
- data.add("C");
- data.add("D");
- data.add("E");
- data.add("F");
- exchange.getIn().setBody(data);
-
- Iterator it = (Iterator) evaluateExpression("${skip(2)}", null);
- assertEquals("C", it.next());
- assertEquals("D", it.next());
- assertEquals("E", it.next());
- assertEquals("F", it.next());
- assertFalse(it.hasNext());
- }
-
- @Test
- public void testSkipDynamic() {
- List<Object> data = new ArrayList<>();
- data.add("A");
- data.add("B");
- data.add("C");
- data.add("D");
- data.add("E");
- data.add("F");
- exchange.getIn().setBody(data);
- exchange.getIn().setHeader("num", 4);
-
- Iterator it = (Iterator) evaluateExpression("${skip(${header.num})}",
null);
- assertEquals("E", it.next());
- assertEquals("F", it.next());
- assertFalse(it.hasNext());
- }
-
- @Test
- public void testJoinBody() {
- List<Object> data = new ArrayList<>();
- data.add("A");
- data.add("B");
- data.add("C");
- exchange.getIn().setBody(data);
-
- assertExpression("${join()}", "A,B,C");
- assertExpression("${join(;)}", "A;B;C");
- assertExpression("${join(' ')}", "A B C");
- assertExpression("${join(',','id=')}", "id=A,id=B,id=C");
- assertExpression("${join(&,id=)}", "id=A&id=B&id=C");
- }
-
- @Test
- public void testJoinHeader() {
- List<Object> data = new ArrayList<>();
- data.add("A");
- data.add("B");
- data.add("C");
- exchange.getIn().setHeader("id", data);
-
- assertExpression("${join('&','id=','${header.id}')}",
"id=A&id=B&id=C");
- }
-
- @Test
- public void testRandomExpression() {
- int min = 1;
- int max = 10;
- int iterations = 30;
- int i = 0;
- for (i = 0; i < iterations; i++) {
- Expression expression =
context.resolveLanguage("simple").createExpression("${random(1,10)}");
- assertTrue(
- min <= expression.evaluate(exchange, Integer.class) &&
expression.evaluate(exchange, Integer.class) < max);
- }
- for (i = 0; i < iterations; i++) {
- Expression expression =
context.resolveLanguage("simple").createExpression("${random(10)}");
- assertTrue(0 <= expression.evaluate(exchange, Integer.class) &&
expression.evaluate(exchange, Integer.class) < max);
- }
- Expression expression =
context.resolveLanguage("simple").createExpression("${random(1, 10)}");
- assertTrue(min <= expression.evaluate(exchange, Integer.class) &&
expression.evaluate(exchange, Integer.class) < max);
-
- Expression expression1 =
context.resolveLanguage("simple").createExpression("${random( 10)}");
- assertTrue(0 <= expression1.evaluate(exchange, Integer.class) &&
expression1.evaluate(exchange, Integer.class) < max);
-
- Exception e1 = assertThrows(Exception.class,
- () -> assertExpression("${random(10,21,30)}", null),
- "Should have thrown exception");
-
- assertEquals("Valid syntax: ${random(min,max)} or ${random(max)} was:
random(10,21,30)", e1.getCause().getMessage());
-
- Exception e2 = assertThrows(Exception.class,
- () -> assertExpression("${random()}", null),
- "Should have thrown exception");
-
- assertEquals("Valid syntax: ${random(min,max)} or ${random(max)} was:
random()", e2.getCause().getMessage());
-
- exchange.getIn().setHeader("max", 20);
- Expression expression3 =
context.resolveLanguage("simple").createExpression("${random(10,${header.max})}");
- int num = expression3.evaluate(exchange, Integer.class);
- assertTrue(num >= 0 && num < 20, "Should be 10..20");
- }
-
@Test
public void testReplaceAllExpression() {
exchange.getMessage().setBody("Hello a how are you");
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/AbstractSimpleFunctionFactoryTestSupport.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/AbstractSimpleFunctionFactoryTestSupport.java
new file mode 100644
index 000000000000..041975cb2d3c
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/AbstractSimpleFunctionFactoryTestSupport.java
@@ -0,0 +1,45 @@
+/*
+ * 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.language.simple.functions;
+
+import org.apache.camel.ExchangeTestSupport;
+import org.apache.camel.Expression;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public abstract class AbstractSimpleFunctionFactoryTestSupport extends
ExchangeTestSupport {
+
+ protected abstract SimpleLanguageFunctionFactory createFactory();
+
+ protected Object evaluate(String function) {
+ return evaluate(function, Object.class);
+ }
+
+ protected <T> T evaluate(String function, Class<T> type) {
+ Expression expression =
context.resolveLanguage("simple").createExpression("${" + function + "}");
+ expression.init(context);
+ return expression.evaluate(exchange, type);
+ }
+
+ @SuppressWarnings("deprecation")
+ protected String createCode(String function) {
+ String code = createFactory().createCode(context, function, 0);
+ assertNotNull(code, "No code could be created for function: " +
function);
+ return code;
+ }
+}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/CollateFunctionFactoryTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/CollateFunctionFactoryTest.java
new file mode 100644
index 000000000000..65d959725568
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/CollateFunctionFactoryTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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.language.simple.functions;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+public class CollateFunctionFactoryTest extends
AbstractSimpleFunctionFactoryTestSupport {
+
+ @Override
+ protected SimpleLanguageFunctionFactory createFactory() {
+ return new CollateFunctionFactory();
+ }
+
+ @Test
+ public void testCollateEven() {
+ List<Object> data = new ArrayList<>();
+ data.add("A");
+ data.add("B");
+ data.add("C");
+ data.add("D");
+ data.add("E");
+ data.add("F");
+ exchange.getIn().setBody(data);
+
+ Iterator<?> it = (Iterator<?>) evaluate("collate(3)");
+ List<?> chunk = (List<?>) it.next();
+ List<?> chunk2 = (List<?>) it.next();
+ assertFalse(it.hasNext());
+
+ assertEquals(3, chunk.size());
+ assertEquals(3, chunk2.size());
+ assertEquals("A", chunk.get(0));
+ assertEquals("B", chunk.get(1));
+ assertEquals("C", chunk.get(2));
+ assertEquals("D", chunk2.get(0));
+ assertEquals("E", chunk2.get(1));
+ assertEquals("F", chunk2.get(2));
+ }
+
+ @Test
+ public void testCollateOdd() {
+ List<Object> data = new ArrayList<>();
+ data.add("A");
+ data.add("B");
+ data.add("C");
+ data.add("D");
+ data.add("E");
+ data.add("F");
+ data.add("G");
+ exchange.getIn().setBody(data);
+
+ Iterator<?> it = (Iterator<?>) evaluate("collate(3)");
+ List<?> chunk = (List<?>) it.next();
+ List<?> chunk2 = (List<?>) it.next();
+ List<?> chunk3 = (List<?>) it.next();
+ assertFalse(it.hasNext());
+
+ assertEquals(3, chunk.size());
+ assertEquals(3, chunk2.size());
+ assertEquals(1, chunk3.size());
+ assertEquals("A", chunk.get(0));
+ assertEquals("B", chunk.get(1));
+ assertEquals("C", chunk.get(2));
+ assertEquals("D", chunk2.get(0));
+ assertEquals("E", chunk2.get(1));
+ assertEquals("F", chunk2.get(2));
+ assertEquals("G", chunk3.get(0));
+ }
+
+ @Test
+ public void testCollateDynamic() {
+ List<Object> data = new ArrayList<>();
+ data.add("A");
+ data.add("B");
+ data.add("C");
+ data.add("D");
+ data.add("E");
+ data.add("F");
+ data.add("G");
+ exchange.getIn().setBody(data);
+ exchange.getIn().setHeader("num", 3);
+
+ Iterator<?> it = (Iterator<?>) evaluate("collate(${header.num})");
+ List<?> chunk = (List<?>) it.next();
+ List<?> chunk2 = (List<?>) it.next();
+ List<?> chunk3 = (List<?>) it.next();
+ assertFalse(it.hasNext());
+
+ assertEquals(3, chunk.size());
+ assertEquals(3, chunk2.size());
+ assertEquals(1, chunk3.size());
+ assertEquals("A", chunk.get(0));
+ assertEquals("B", chunk.get(1));
+ assertEquals("C", chunk.get(2));
+ assertEquals("D", chunk2.get(0));
+ assertEquals("E", chunk2.get(1));
+ assertEquals("F", chunk2.get(2));
+ assertEquals("G", chunk3.get(0));
+ }
+
+ @Test
+ public void testCreateCode() {
+ assertEquals("collate(exchange, 10)", createCode("collate(10)"));
+ assertEquals("collate(exchange, ${header.max})",
createCode("collate(${header.max})"));
+ }
+}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/JoinFunctionFactoryTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/JoinFunctionFactoryTest.java
new file mode 100644
index 000000000000..ef1389ac0434
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/JoinFunctionFactoryTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.language.simple.functions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class JoinFunctionFactoryTest extends
AbstractSimpleFunctionFactoryTestSupport {
+
+ @Override
+ protected SimpleLanguageFunctionFactory createFactory() {
+ return new JoinFunctionFactory();
+ }
+
+ @Test
+ public void testJoinBody() {
+ List<Object> data = new ArrayList<>();
+ data.add("A");
+ data.add("B");
+ data.add("C");
+ exchange.getIn().setBody(data);
+
+ assertEquals("A,B,C", evaluate("join()", String.class));
+ assertEquals("A;B;C", evaluate("join(;)", String.class));
+ assertEquals("A B C", evaluate("join(' ')", String.class));
+ assertEquals("id=A,id=B,id=C", evaluate("join(',','id=')",
String.class));
+ assertEquals("id=A&id=B&id=C", evaluate("join(&,id=)", String.class));
+ }
+
+ @Test
+ public void testJoinHeader() {
+ List<Object> data = new ArrayList<>();
+ data.add("A");
+ data.add("B");
+ data.add("C");
+ exchange.getIn().setHeader("id", data);
+
+ assertEquals("id=A&id=B&id=C",
evaluate("join('&','id=','${header.id}')", String.class));
+ }
+
+ @Test
+ public void testCreateCode() {
+ assertEquals("var val = body;\n return join(exchange, val,
\",\", null);", createCode("join()"));
+ }
+}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/RandomFunctionFactoryTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/RandomFunctionFactoryTest.java
new file mode 100644
index 000000000000..72c01212584f
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/RandomFunctionFactoryTest.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.language.simple.functions;
+
+import org.apache.camel.Expression;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class RandomFunctionFactoryTest extends
AbstractSimpleFunctionFactoryTestSupport {
+
+ @Override
+ protected SimpleLanguageFunctionFactory createFactory() {
+ return new RandomFunctionFactory();
+ }
+
+ @Test
+ public void testRandomExpression() {
+ int min = 1;
+ int max = 10;
+
+ for (int i = 0; i < 30; i++) {
+ Expression expression = createFactory().createFunction(context,
"random(1,10)", 0);
+ expression.init(context);
+ int num = expression.evaluate(exchange, Integer.class);
+ assertTrue(min <= num && num < max);
+ }
+ for (int i = 0; i < 30; i++) {
+ Expression expression = createFactory().createFunction(context,
"random(10)", 0);
+ expression.init(context);
+ int num = expression.evaluate(exchange, Integer.class);
+ assertTrue(0 <= num && num < max);
+ }
+
+ int num1 = evaluate("random(1, 10)", Integer.class);
+ assertTrue(min <= num1 && num1 < max);
+
+ int num2 = evaluate("random( 10)", Integer.class);
+ assertTrue(0 <= num2 && num2 < max);
+
+ Exception e1 = assertThrows(Exception.class,
+ () -> evaluate("random(10,21,30)", Object.class),
+ "Should have thrown exception");
+ assertEquals("Valid syntax: ${random(min,max)} or ${random(max)} was:
random(10,21,30)", e1.getCause().getMessage());
+
+ Exception e2 = assertThrows(Exception.class,
+ () -> evaluate("random()", Object.class),
+ "Should have thrown exception");
+ assertEquals("Valid syntax: ${random(min,max)} or ${random(max)} was:
random()", e2.getCause().getMessage());
+
+ exchange.getIn().setHeader("max", 20);
+ int num = evaluate("random(10,${header.max})", Integer.class);
+ assertTrue(num >= 0 && num < 20, "Should be 10..20");
+ }
+
+ @Test
+ public void testCreateCode() {
+ assertEquals("random(exchange, 0, 10)", createCode("random(10)"));
+ assertEquals("random(exchange, 10, 20)", createCode("random(10, 20)"));
+ assertEquals("random(exchange, 10, ${header.max})",
createCode("random(10, ${header.max})"));
+ assertEquals("random(exchange, ${header.min}, ${header.max})",
createCode("random(${header.min}, ${header.max})"));
+ }
+}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/SkipFunctionFactoryTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/SkipFunctionFactoryTest.java
new file mode 100644
index 000000000000..59e5a8a51d83
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/SkipFunctionFactoryTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.language.simple.functions;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+public class SkipFunctionFactoryTest extends
AbstractSimpleFunctionFactoryTestSupport {
+
+ @Override
+ protected SimpleLanguageFunctionFactory createFactory() {
+ return new SkipFunctionFactory();
+ }
+
+ @Test
+ public void testSkip() {
+ List<Object> data = new ArrayList<>();
+ data.add("A");
+ data.add("B");
+ data.add("C");
+ data.add("D");
+ data.add("E");
+ data.add("F");
+ exchange.getIn().setBody(data);
+
+ Iterator<?> it = (Iterator<?>) evaluate("skip(2)");
+ assertEquals("C", it.next());
+ assertEquals("D", it.next());
+ assertEquals("E", it.next());
+ assertEquals("F", it.next());
+ assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void testSkipDynamic() {
+ List<Object> data = new ArrayList<>();
+ data.add("A");
+ data.add("B");
+ data.add("C");
+ data.add("D");
+ data.add("E");
+ data.add("F");
+ exchange.getIn().setBody(data);
+ exchange.getIn().setHeader("num", 4);
+
+ Iterator<?> it = (Iterator<?>) evaluate("skip(${header.num})");
+ assertEquals("E", it.next());
+ assertEquals("F", it.next());
+ assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void testCreateCode() {
+ assertEquals("skip(exchange, 10)", createCode("skip(10)"));
+ assertEquals("skip(exchange, ${header.max})",
createCode("skip(${header.max})"));
+ assertEquals("skip(exchange, ${random(2,3)})",
createCode("skip(${random(2,3)})"));
+ }
+}