This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch ic in repository https://gitbox.apache.org/repos/asf/camel.git
commit 319bdee4748eb7b10458cba04d99377876014dfc Author: Claus Ibsen <[email protected]> AuthorDate: Fri Jan 30 11:37:27 2026 +0100 CAMEL-22899: camel-core - Simple language - Add custom function in init block via chains --- .../modules/languages/pages/simple-language.adoc | 11 ++++++- .../simple/DefaultSimpleFunctionRegistry.java | 16 ++++++++- .../language/simple/SimpleExpressionBuilder.java | 38 ++++++++++++++++++++++ .../language/simple/SimpleExpressionParser.java | 3 ++ .../simple/ast/SimpleFunctionExpression.java | 23 +++++++++++++ .../language/simple/SimpleInitBlockChainTest.java | 15 +++++++++ 6 files changed, 104 insertions(+), 2 deletions(-) diff --git a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc index 827e990751dd..ef750015a187 100644 --- a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc +++ b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc @@ -1272,6 +1272,8 @@ $init{ }init$ ---- +NOTE: You cannot declare custom functions that call other function functions. This is currently not supported. + The function will by default use the message body as the input, such that the following: [source,java] @@ -1281,7 +1283,14 @@ simple("Incoming message: $cleanUp()"); Would then call the _clean_ function with the message body as the input, which will then be used for trim, normalize and upper-casing. -NOTE: You cannot declare custom functions that call other function functions. This is currently not supported. +A custom function can also use a **single** parameter, however then the syntax must use `${name(...)}` style, such as: + +[source,java] +---- +simple("Incoming message: ${cleanUp(' Please clean this text for me ')}"); +---- + +Here the parameter is a fixed `String` but you can also pass in other type of value such as a number, boolean, or even a nested function. == OGNL Expression Support diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/DefaultSimpleFunctionRegistry.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/DefaultSimpleFunctionRegistry.java index f7227c936d85..cb351b103b50 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/DefaultSimpleFunctionRegistry.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/DefaultSimpleFunctionRegistry.java @@ -19,16 +19,30 @@ package org.apache.camel.language.simple; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; import org.apache.camel.Expression; import org.apache.camel.NonManagedService; import org.apache.camel.support.service.ServiceSupport; -public class DefaultSimpleFunctionRegistry extends ServiceSupport implements SimpleFunctionRegistry, NonManagedService { +public class DefaultSimpleFunctionRegistry extends ServiceSupport implements CamelContextAware, SimpleFunctionRegistry, NonManagedService { private final Map<String, Expression> functions = new ConcurrentHashMap<>(); + private CamelContext camelContext; + + @Override + public CamelContext getCamelContext() { + return camelContext; + } + + @Override + public void setCamelContext(CamelContext camelContext) { + this.camelContext = camelContext; + } @Override public void addFunction(String name, Expression expression) { + expression.init(camelContext); functions.put(name, expression); } diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java index f99ac465b254..e132ce47751f 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java @@ -2863,6 +2863,44 @@ public final class SimpleExpressionBuilder { }; } + public static Expression customFunction(final String name, final String parameter) { + return new ExpressionAdapter() { + private Expression func; + private Expression exp; + + @Override + public void init(CamelContext context) { + super.init(context); + SimpleFunctionRegistry registry + = context.getCamelContextExtension().getContextPlugin(SimpleFunctionRegistry.class); + func = registry.getFunction(name); + if (func == null) { + throw new IllegalArgumentException("No custom simple function with name: " + name); + } + exp = ExpressionBuilder.simpleExpression(parameter); + } + + @Override + public Object evaluate(Exchange exchange) { + final Object originalBody = exchange.getMessage().getBody(); + try { + Object input = exp.evaluate(exchange, Object.class); + if (input != null) { + exchange.getMessage().setBody(input); + return func.evaluate(exchange, Object.class); + } + return null; + } finally { + exchange.getMessage().setBody(originalBody); + } + } + + public String toString() { + return "function(" + name + ")"; + } + }; + } + /** * Expression adapter for OGNL expression from Message Header or Exchange property */ diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionParser.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionParser.java index 347ddb58f63a..c0771c6de995 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionParser.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionParser.java @@ -95,7 +95,10 @@ public class SimpleExpressionParser extends BaseSimpleParser { } // use $$key() as local function in the expression afterwards for (String key : initParser.getInitFunctions()) { + // no-arg functions this.expression = this.expression.replace("$" + key + "()", "${function." + key + "}"); + // arg functions + this.expression = this.expression.replace("${" + key + "(", "${function(" + key + ","); } } 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 d0ea95103ac3..5df606606e8e 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 @@ -620,6 +620,29 @@ public class SimpleFunctionExpression extends LiteralExpression { return answer; } + remainder = ifStartsWithReturnRemainder("function(", function); + if (remainder != null) { + String key; + String param; + String values = StringHelper.beforeLast(remainder, ")"); + if (values == null || ObjectHelper.isEmpty(values)) { + throw new SimpleParserException( + "Valid syntax: ${function(key,exp)} was: " + function, + token.getIndex()); + } + String[] tokens = StringQuoteHelper.splitSafeQuote(values, ',', true, true); + if (tokens.length != 2) { + throw new SimpleParserException( + "Valid syntax: ${function(key,exp)} was: " + function, + token.getIndex()); + } + key = StringHelper.removeQuotes(tokens[0]); + key = key.trim(); + param = tokens[1]; + param = StringHelper.removeLeadingAndEndingQuotes(param.trim()); + return SimpleExpressionBuilder.customFunction(key, param); + } + return null; } diff --git a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleInitBlockChainTest.java b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleInitBlockChainTest.java index 0eb4f44c59f0..6f2b5170cda2 100644 --- a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleInitBlockChainTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleInitBlockChainTest.java @@ -36,6 +36,14 @@ public class SimpleInitBlockChainTest extends LanguageTestSupport { You said: $clean() in $count() words """; + private static final String INIT3 = """ + $init{ + $clean ~:= ${trim()} ~> ${normalizeWhitespace()} ~> ${uppercase()} + }init$ + You said: ${clean(' Clean this text please ... ')} and then do something else + """; + + @Test public void testInitBlockChain() throws Exception { exchange.getMessage().setBody(" Hello big World "); @@ -50,6 +58,13 @@ public class SimpleInitBlockChainTest extends LanguageTestSupport { assertExpression(exchange, INIT2, "You said: HELLO BIG WORLD in 3 words\n"); } + @Test + public void testInitBlockChain3() throws Exception { + exchange.getMessage().setBody("Hello World"); + + assertExpression(exchange, INIT3, "You said: CLEAN THIS TEXT PLEASE ... and then do something else\n"); + } + @Override protected String getLanguageName() { return "simple";
