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",

Reply via email to