This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch camel-4.18.x in repository https://gitbox.apache.org/repos/asf/camel.git
commit 6ad1ea9cf4908ee75b0ea58bcf4b6a2716eb1272 Author: Claus Ibsen <[email protected]> AuthorDate: Sat Feb 21 20:05:25 2026 +0100 CAMEL-23047: camel-core - Add val function to simple --- .../org/apache/camel/catalog/languages/simple.json | 9 ++--- .../language/csimple/joor/OriginalSimpleTest.java | 18 ++++++++++ .../org/apache/camel/language/simple/simple.json | 9 ++--- .../modules/languages/pages/simple-language.adoc | 1 + .../camel/language/simple/SimpleConstants.java | 4 +++ .../simple/ast/SimpleFunctionExpression.java | 28 ++++++++++++++++ .../camel/language/simple/SimpleInitBlockTest.java | 39 ++++++++++++++++++++++ .../apache/camel/language/simple/SimpleTest.java | 22 ++++++++++++ .../java/org/apache/camel/util/SimpleUtils.java | 1 + 9 files changed, 123 insertions(+), 8 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json index 0ccdfe9ecbe1..20b4de518fef 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json @@ -136,9 +136,10 @@ "unquote(exp)": { "index": 108, "kind": "function", "displayName": "Unquote", "group": "string", "label": "string", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns the message body (or expression) with any leading\/ending quotes removed", "ognl": false, "suffix": "}" }, "uppercase(exp)": { "index": 109, "kind": "function", "displayName": "Uppercase", "group": "string", "label": "string", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Uppercases the message body (or expression)", "ognl": false, "suffix": "}" }, "uuid(type)": { "index": 110, "kind": "function", "displayName": "Generate UUID", "group": "other", "label": "other", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a UUID using the Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and `simple` as the type. If no type is given, the default is used. It is also possible to use a custom `UuidGenera [...] - "variable.name": { "index": 111, "kind": "function", "displayName": "Variable", "group": "core", "label": "core", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The variable with the given name", "ognl": true, "suffix": "}" }, - "variableAs(key,type)": { "index": 112, "kind": "function", "displayName": "Variable As", "group": "core", "label": "core", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Converts the variable to the given type (classname).", "ognl": false, "suffix": "}" }, - "variables": { "index": 113, "kind": "function", "displayName": "Variables", "group": "core", "label": "core", "required": false, "javaType": "java.util.Map", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns all the variables from the current Exchange in a Map", "ognl": false, "suffix": "}" }, - "xpath(input,exp)": { "index": 114, "kind": "function", "displayName": "XPath", "group": "xml", "label": "xml", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "When working with XML data, then this allows using the XPath language, for example, to extract data from the message body (in XML format). This requires having camel-xpath JAR on the classpath. For input (optional), you ca [...] + "val(exp)": { "index": 111, "kind": "function", "displayName": "Value", "group": "core", "label": "core", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns the expression as a constant value", "ognl": false, "suffix": "}" }, + "variable.name": { "index": 112, "kind": "function", "displayName": "Variable", "group": "core", "label": "core", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The variable with the given name", "ognl": true, "suffix": "}" }, + "variableAs(key,type)": { "index": 113, "kind": "function", "displayName": "Variable As", "group": "core", "label": "core", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Converts the variable to the given type (classname).", "ognl": false, "suffix": "}" }, + "variables": { "index": 114, "kind": "function", "displayName": "Variables", "group": "core", "label": "core", "required": false, "javaType": "java.util.Map", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns all the variables from the current Exchange in a Map", "ognl": false, "suffix": "}" }, + "xpath(input,exp)": { "index": 115, "kind": "function", "displayName": "XPath", "group": "xml", "label": "xml", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "When working with XML data, then this allows using the XPath language, for example, to extract data from the message body (in XML format). This requires having camel-xpath JAR on the classpath. For input (optional), you ca [...] } } diff --git a/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java b/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java index 27fe37ac8efb..069b5566c72d 100644 --- a/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java +++ b/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java @@ -2867,6 +2867,24 @@ public class OriginalSimpleTest extends LanguageTestSupport { assertEquals("carlsberg", s); } + @Test + public void testVal() { + exchange.getMessage().setBody(123); + + Expression expression = context.resolveLanguage("csimple").createExpression("${val(abc)}"); + String s = expression.evaluate(exchange, String.class); + assertEquals("abc", s); + + expression = context.resolveLanguage("csimple").createExpression("${val(${body})}"); + s = expression.evaluate(exchange, String.class); + assertEquals("123", s); + + expression = context.resolveLanguage("csimple").createExpression("${val(${body})}"); + Object obj = expression.evaluate(exchange, Object.class); + assertIsInstanceOf(Integer.class, obj); + assertEquals(123, obj); + } + @Test public void testSetHeader() { exchange.getMessage().setBody("Hello World"); diff --git a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/simple.json b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/simple.json index 0ccdfe9ecbe1..20b4de518fef 100644 --- a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/simple.json +++ b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/simple.json @@ -136,9 +136,10 @@ "unquote(exp)": { "index": 108, "kind": "function", "displayName": "Unquote", "group": "string", "label": "string", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns the message body (or expression) with any leading\/ending quotes removed", "ognl": false, "suffix": "}" }, "uppercase(exp)": { "index": 109, "kind": "function", "displayName": "Uppercase", "group": "string", "label": "string", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Uppercases the message body (or expression)", "ognl": false, "suffix": "}" }, "uuid(type)": { "index": 110, "kind": "function", "displayName": "Generate UUID", "group": "other", "label": "other", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a UUID using the Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and `simple` as the type. If no type is given, the default is used. It is also possible to use a custom `UuidGenera [...] - "variable.name": { "index": 111, "kind": "function", "displayName": "Variable", "group": "core", "label": "core", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The variable with the given name", "ognl": true, "suffix": "}" }, - "variableAs(key,type)": { "index": 112, "kind": "function", "displayName": "Variable As", "group": "core", "label": "core", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Converts the variable to the given type (classname).", "ognl": false, "suffix": "}" }, - "variables": { "index": 113, "kind": "function", "displayName": "Variables", "group": "core", "label": "core", "required": false, "javaType": "java.util.Map", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns all the variables from the current Exchange in a Map", "ognl": false, "suffix": "}" }, - "xpath(input,exp)": { "index": 114, "kind": "function", "displayName": "XPath", "group": "xml", "label": "xml", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "When working with XML data, then this allows using the XPath language, for example, to extract data from the message body (in XML format). This requires having camel-xpath JAR on the classpath. For input (optional), you ca [...] + "val(exp)": { "index": 111, "kind": "function", "displayName": "Value", "group": "core", "label": "core", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns the expression as a constant value", "ognl": false, "suffix": "}" }, + "variable.name": { "index": 112, "kind": "function", "displayName": "Variable", "group": "core", "label": "core", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The variable with the given name", "ognl": true, "suffix": "}" }, + "variableAs(key,type)": { "index": 113, "kind": "function", "displayName": "Variable As", "group": "core", "label": "core", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Converts the variable to the given type (classname).", "ognl": false, "suffix": "}" }, + "variables": { "index": 114, "kind": "function", "displayName": "Variables", "group": "core", "label": "core", "required": false, "javaType": "java.util.Map", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns all the variables from the current Exchange in a Map", "ognl": false, "suffix": "}" }, + "xpath(input,exp)": { "index": 115, "kind": "function", "displayName": "XPath", "group": "xml", "label": "xml", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "When working with XML data, then this allows using the XPath language, for example, to extract data from the message body (in XML format). This requires having camel-xpath JAR on the classpath. For input (optional), you ca [...] } } 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 cc971b83f780..3d02ba4c3763 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 @@ -186,6 +186,7 @@ to access Camel functionality and content of the message being routed. |`stepId` | `String` | Returns the id of the current step the `Exchange` is being routed. Returns `null` if there are no steps. |`throwException(type,msg)` | `Exception` | Deliberately throws an error. Uses `IllegalArgumentException` by default if no type is specified (use fully qualified classname). |`type:name.field` | `Object` | To refer to a type or field by its fully qualified classname. For example: `type:org.apache.camel.Exchange.FILE_NAME`. +|`val(exp)` | `Object` | |`variable.key` | `Object` | To look up the variable with the given key. |`variable.key._OGNL_` | `Object` | To look up the variable with the given key and then invoke Camel _OGNL syntax_. |`variable[key]` | `Object` | *Deprecated* To look up the variable with the given key. diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleConstants.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleConstants.java index a408692a33fb..5d2accbbdefa 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleConstants.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleConstants.java @@ -450,6 +450,10 @@ public final class SimpleConstants { label = "other", javaType = "String", displayName = "Generate UUID") public static final String UUID = "uuid(type)"; + @Metadata(description = "Returns the expression as a constant value", + label = "core", javaType = "Object", displayName = "Value") + public static final String VAL = "val(exp)"; + @Metadata(description = "The variable with the given name", label = "core,ognl", javaType = "Object") public static final String VARIABLE = "variable.name"; 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 0541b094e630..7b56bdf513db 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 @@ -1317,6 +1317,19 @@ public class SimpleFunctionExpression extends LiteralExpression { return SimpleExpressionBuilder.trimExpression(exp); } + // val function + remainder = ifStartsWithReturnRemainder("val(", function); + if (remainder != null) { + String exp = null; + String value = StringHelper.beforeLast(remainder, ")"); + if (value == null || ObjectHelper.isEmpty(value)) { + throw new SimpleParserException( + "Valid syntax: ${val(exp)} was: " + function, + token.getIndex()); + } + return ExpressionBuilder.simpleExpression(value); + } + // capitalize remainder = ifStartsWithReturnRemainder("capitalize(", function); if (remainder != null) { @@ -3231,6 +3244,21 @@ public class SimpleFunctionExpression extends LiteralExpression { return "Object o = " + exp + ";\n return trim(exchange, o);"; } + // val function + remainder = ifStartsWithReturnRemainder("val(", function); + if (remainder != null) { + String values = StringHelper.beforeLast(remainder, ")"); + if (values == null || ObjectHelper.isEmpty(values)) { + throw new SimpleParserException( + "Valid syntax: ${val(exp)} was: " + function, + token.getIndex()); + } + String s = values; + s = StringHelper.removeLeadingAndEndingQuotes(s); + s = StringQuoteHelper.doubleQuote(s); + return "Object o = " + s + ";\n return o;"; + } + // isEmpty function remainder = ifStartsWithReturnRemainder("isEmpty(", function); if (remainder != null) { diff --git a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleInitBlockTest.java b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleInitBlockTest.java index 2af7bc087c1e..cae5757d4afd 100644 --- a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleInitBlockTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleInitBlockTest.java @@ -16,10 +16,13 @@ */ package org.apache.camel.language.simple; +import org.apache.camel.Expression; import org.apache.camel.LanguageTestSupport; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class SimpleInitBlockTest extends LanguageTestSupport { private static final String INIT = """ @@ -106,6 +109,42 @@ public class SimpleInitBlockTest extends LanguageTestSupport { assertExpression(exchange, INIT4, "orderId=123,total=208\n"); } + @Test + public void testInitBlockAverageFunction() { + String exp = """ + $init{ + $a := ${body} + $b := ${header.foo} + $c := ${header.bar} + }init$ + average: ${average($a,$b,$c)} + """; + + exchange.getMessage().setBody(1); + exchange.getMessage().setHeader("foo", 2); + exchange.getMessage().setHeader("bar", 3); + + Expression expression = context.resolveLanguage("simple").createExpression(exp); + String s = expression.evaluate(exchange, String.class); + assertEquals("average: 2\n", s); + } + + @Test + public void testInitBlockAverageVal() { + String exp = """ + $init{ + $a := ${val(4)} + $b := ${val(5)} + $c := ${val(6)} + }init$ + average: ${average($a,$b,$c)} + """; + + Expression expression = context.resolveLanguage("simple").createExpression(exp); + String s = expression.evaluate(exchange, String.class); + assertEquals("average: 5\n", s); + } + @Override protected String getLanguageName() { return "simple"; 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 b6554b08653d..cc92d6dfc9ac 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 @@ -3193,6 +3193,10 @@ public class SimpleTest extends LanguageTestSupport { s = expression.evaluate(exchange, String.class); assertEquals("Hello World", s); + expression = context.resolveLanguage("simple").createExpression("${concat('a','b')}"); + s = expression.evaluate(exchange, String.class); + assertEquals("ab", s); + expression = context.resolveLanguage("simple").createExpression("${concat(${body}, 'World', '_')}"); s = expression.evaluate(exchange, String.class); assertEquals("Hello_World", s); @@ -3301,6 +3305,24 @@ public class SimpleTest extends LanguageTestSupport { assertEquals("Hi Camel", out); } + @Test + public void testVal() { + exchange.getMessage().setBody(123); + + Expression expression = context.resolveLanguage("simple").createExpression("${val(abc)}"); + String s = expression.evaluate(exchange, String.class); + assertEquals("abc", s); + + expression = context.resolveLanguage("simple").createExpression("${val(${body})}"); + s = expression.evaluate(exchange, String.class); + assertEquals("123", s); + + expression = context.resolveLanguage("simple").createExpression("${val(${body})}"); + Object obj = expression.evaluate(exchange, Object.class); + assertIsInstanceOf(Integer.class, obj); + assertEquals(123, obj); + } + @Test public void testSetHeader() { exchange.getMessage().setBody("Hello World"); diff --git a/core/camel-util/src/main/java/org/apache/camel/util/SimpleUtils.java b/core/camel-util/src/main/java/org/apache/camel/util/SimpleUtils.java index 2f477a1ada86..ec9922efcbcd 100644 --- a/core/camel-util/src/main/java/org/apache/camel/util/SimpleUtils.java +++ b/core/camel-util/src/main/java/org/apache/camel/util/SimpleUtils.java @@ -135,6 +135,7 @@ public class SimpleUtils { "unquote", "uppercase", "uuid", + "val", "variable", "variableas", "variables",
