You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2026/01/13 14:30:07 UTC
(camel) branch main updated: CAMEL-22852: camel-core - Add length/size function to simple language (#20799)
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 09e516fe9e34 CAMEL-22852: camel-core - Add length/size function to simple language (#20799)
09e516fe9e34 is described below
commit 09e516fe9e342751d039dc6e4e41d0f396a47db3
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Jan 13 15:30:00 2026 +0100
CAMEL-22852: camel-core - Add length/size function to simple language (#20799)
---
.../org/apache/camel/catalog/languages/simple.json | 42 ++++---
.../language/csimple/joor/OriginalSimpleTest.java | 51 ++++++++
.../org/apache/camel/language/simple/simple.json | 42 ++++---
.../modules/languages/pages/simple-language.adoc | 4 +
.../camel/language/csimple/CSimpleHelper.java | 67 +++++++++++
.../camel/language/simple/SimpleConstants.java | 6 +
.../language/simple/SimpleExpressionBuilder.java | 134 +++++++++++++++++++++
.../simple/ast/SimpleFunctionExpression.java | 70 +++++++++++
.../apache/camel/language/simple/SimpleTest.java | 50 ++++++++
9 files changed, 426 insertions(+), 40 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 a05d2db62f8b..c9c573a035eb 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
@@ -72,25 +72,27 @@
"random(min,max)": { "index": 46, "kind": "function", "displayName": "Generate Random Number", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a random number between min (included) and max (excluded).", "ognl": false, "suffix": "}" },
"skip(num)": { "index": 47, "kind": "function", "displayName": "Skip First Items from the Message Body", "group": "function", "label": "function", "required": false, "javaType": "java.util.Iterator", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The skip function iterates the message body and skips the first number of items. This can be used with the Splitter EIP to split a message body and skip the first N number of [...]
"trim(exp)": { "index": 48, "kind": "function", "displayName": "Trim", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The trim function trims the message body (or expression) by removing all leading and trailing white spaces.", "ognl": false, "suffix": "}" },
- "uppercase(exp)": { "index": 49, "kind": "function", "displayName": "Uppercase", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Uppercases the message body (or expression)", "ognl": false, "suffix": "}" },
- "lowercase(exp)": { "index": 50, "kind": "function", "displayName": "Lowercase", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Lowercases the message body (or expression)", "ognl": false, "suffix": "}" },
- "concat(exp,exp,separator)": { "index": 51, "kind": "function", "displayName": "Concat", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Performs a string concat using two expressions (message body as default) with optional separator", "ognl": false, "suffix": "}" },
- "collate(num)": { "index": 52, "kind": "function", "displayName": "Group Message Body into Sub Lists", "group": "function", "label": "function", "required": false, "javaType": "java.util.Iterator", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The collate function iterates the message body and groups the data into sub lists of specified size. This can be used with the Splitter EIP to split a message body and group\/ba [...]
- "join(separator,prefix,exp)": { "index": 53, "kind": "function", "displayName": "Join", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The join function iterates the message body\/expression and joins the data into a string. The separator is by default a comma. The prefix is optional. The join uses the message body as source by default. [...]
- "messageHistory(boolean)": { "index": 54, "kind": "function", "displayName": "Print Message History", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message history of the current exchange (how it has been routed). This is similar to the route stack-trace message history the error handler logs in case of an unhandled exception. The b [...]
- "uuid(type)": { "index": 55, "kind": "function", "displayName": "Generate UUID", "group": "function", "label": "function", "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 `UuidG [...]
- "hash(exp,algorithm)": { "index": 56, "kind": "function", "displayName": "Compute Hash Value", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a hashed value (string in hex decimal) of the message body\/expression using JDK MessageDigest. The algorithm can be SHA-256 (default) or SHA3-256.", "ognl": false, "suffix": "}" },
- "empty(type)": { "index": 57, "kind": "function", "displayName": "Create Empty Object", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Creates a new empty object (decided by type). Use `string` to create an empty String. Use `list` to create an empty `java.util.ArrayList`. Use `map` to create an empty `java.util.LinkedHashMap`.", "ognl": [...]
- "iif(predicate,trueExp,falseExp)": { "index": 58, "kind": "function", "displayName": "If Then Else", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Evaluates the predicate and returns the value of trueExp or falseExp. This function is similar to the ternary operator in Java.", "ognl": false, "suffix": "}" },
- "list(val...)": { "index": 59, "kind": "function", "displayName": "Create List of values", "group": "function", "label": "function", "required": false, "javaType": "java.util.ArrayList", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The list function creates an ArrayList with the given set of values.", "ognl": false, "suffix": "}" },
- "map(key1,value1,...)": { "index": 60, "kind": "function", "displayName": "Create Map of pairs", "group": "function", "label": "function", "required": false, "javaType": "java.util.LinkedHashMap", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The map function creates a LinkedHashMap with the given set of pairs.", "ognl": false, "suffix": "}" },
- "attachments": { "index": 61, "kind": "function", "displayName": "Attachments", "group": "function", "label": "function", "required": false, "javaType": "java.util.Map", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "All the attachments as a Map<String,DataHandler.", "ognl": false, "suffix": "}" },
- "attachments.size": { "index": 62, "kind": "function", "displayName": "Attachments", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of attachments. Is 0 if there are no attachments.", "ognl": false, "suffix": "}" },
- "attachmentContentAsText": { "index": 63, "kind": "function", "displayName": "Attachment Content As Text", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the attachment as text (ie String).", "ognl": false, "suffix": "}" },
- "attachmentContent": { "index": 64, "kind": "function", "displayName": "Attachment Content", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the attachment", "ognl": false, "suffix": "}" },
- "attachmentContentAs(type)": { "index": 65, "kind": "function", "displayName": "Attachment Content As", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the attachment, converted to the given type.", "ognl": false, "suffix": "}" },
- "attachmentHeader(key,name)": { "index": 66, "kind": "function", "displayName": "Attachment Header", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The attachment header with the given name.", "ognl": false, "suffix": "}" },
- "attachmentHeader(key,name,type)": { "index": 67, "kind": "function", "displayName": "Attachment Header", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The attachment header with the given name, converted to the given type.", "ognl": false, "suffix": "}" },
- "attachment(key)": { "index": 68, "kind": "function", "displayName": "Attachment", "group": "function", "label": "function", "required": false, "javaType": "jakarta.activation.DataHandler", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The DataHandler for the given attachment.", "ognl": true, "suffix": "}" }
+ "length(exp)": { "index": 49, "kind": "function", "displayName": "Length", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The payload length (number of bytes) of the message body (or expression).", "ognl": false, "suffix": "}" },
+ "size(exp)": { "index": 50, "kind": "function", "displayName": "Size", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the message body (or expression). If the payload is java.util.Collection or java.util.Map based then the size is the number of elements; otherwise the payload size in bytes.", "ognl": false, "suffix": "}" },
+ "uppercase(exp)": { "index": 51, "kind": "function", "displayName": "Uppercase", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Uppercases the message body (or expression)", "ognl": false, "suffix": "}" },
+ "lowercase(exp)": { "index": 52, "kind": "function", "displayName": "Lowercase", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Lowercases the message body (or expression)", "ognl": false, "suffix": "}" },
+ "concat(exp,exp,separator)": { "index": 53, "kind": "function", "displayName": "Concat", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Performs a string concat using two expressions (message body as default) with optional separator", "ognl": false, "suffix": "}" },
+ "collate(num)": { "index": 54, "kind": "function", "displayName": "Group Message Body into Sub Lists", "group": "function", "label": "function", "required": false, "javaType": "java.util.Iterator", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The collate function iterates the message body and groups the data into sub lists of specified size. This can be used with the Splitter EIP to split a message body and group\/ba [...]
+ "join(separator,prefix,exp)": { "index": 55, "kind": "function", "displayName": "Join", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The join function iterates the message body\/expression and joins the data into a string. The separator is by default a comma. The prefix is optional. The join uses the message body as source by default. [...]
+ "messageHistory(boolean)": { "index": 56, "kind": "function", "displayName": "Print Message History", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message history of the current exchange (how it has been routed). This is similar to the route stack-trace message history the error handler logs in case of an unhandled exception. The b [...]
+ "uuid(type)": { "index": 57, "kind": "function", "displayName": "Generate UUID", "group": "function", "label": "function", "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 `UuidG [...]
+ "hash(exp,algorithm)": { "index": 58, "kind": "function", "displayName": "Compute Hash Value", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a hashed value (string in hex decimal) of the message body\/expression using JDK MessageDigest. The algorithm can be SHA-256 (default) or SHA3-256.", "ognl": false, "suffix": "}" },
+ "empty(type)": { "index": 59, "kind": "function", "displayName": "Create Empty Object", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Creates a new empty object (decided by type). Use `string` to create an empty String. Use `list` to create an empty `java.util.ArrayList`. Use `map` to create an empty `java.util.LinkedHashMap`.", "ognl": [...]
+ "iif(predicate,trueExp,falseExp)": { "index": 60, "kind": "function", "displayName": "If Then Else", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Evaluates the predicate and returns the value of trueExp or falseExp. This function is similar to the ternary operator in Java.", "ognl": false, "suffix": "}" },
+ "list(val...)": { "index": 61, "kind": "function", "displayName": "Create List of values", "group": "function", "label": "function", "required": false, "javaType": "java.util.ArrayList", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The list function creates an ArrayList with the given set of values.", "ognl": false, "suffix": "}" },
+ "map(key1,value1,...)": { "index": 62, "kind": "function", "displayName": "Create Map of pairs", "group": "function", "label": "function", "required": false, "javaType": "java.util.LinkedHashMap", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The map function creates a LinkedHashMap with the given set of pairs.", "ognl": false, "suffix": "}" },
+ "attachments": { "index": 63, "kind": "function", "displayName": "Attachments", "group": "function", "label": "function", "required": false, "javaType": "java.util.Map", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "All the attachments as a Map<String,DataHandler.", "ognl": false, "suffix": "}" },
+ "attachments.size": { "index": 64, "kind": "function", "displayName": "Attachments", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of attachments. Is 0 if there are no attachments.", "ognl": false, "suffix": "}" },
+ "attachmentContentAsText": { "index": 65, "kind": "function", "displayName": "Attachment Content As Text", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the attachment as text (ie String).", "ognl": false, "suffix": "}" },
+ "attachmentContent": { "index": 66, "kind": "function", "displayName": "Attachment Content", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the attachment", "ognl": false, "suffix": "}" },
+ "attachmentContentAs(type)": { "index": 67, "kind": "function", "displayName": "Attachment Content As", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the attachment, converted to the given type.", "ognl": false, "suffix": "}" },
+ "attachmentHeader(key,name)": { "index": 68, "kind": "function", "displayName": "Attachment Header", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The attachment header with the given name.", "ognl": false, "suffix": "}" },
+ "attachmentHeader(key,name,type)": { "index": 69, "kind": "function", "displayName": "Attachment Header", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The attachment header with the given name, converted to the given type.", "ognl": false, "suffix": "}" },
+ "attachment(key)": { "index": 70, "kind": "function", "displayName": "Attachment", "group": "function", "label": "function", "required": false, "javaType": "jakarta.activation.DataHandler", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The DataHandler for the given attachment.", "ognl": true, "suffix": "}" }
}
}
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 b3fad07f87b8..26e1a296f589 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
@@ -16,6 +16,7 @@
*/
package org.apache.camel.language.csimple.joor;
+import java.io.File;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.ArrayList;
@@ -2240,6 +2241,56 @@ public class OriginalSimpleTest extends LanguageTestSupport {
assertExpression("${uuid(mygen)}", "1234");
}
+ @Test
+ public void testSize() {
+ exchange.getMessage().setBody(new int[] { 4, 7, 9 });
+ Expression expression = context.resolveLanguage("csimple").createExpression("${size()}");
+ int len = expression.evaluate(exchange, int.class);
+ assertEquals(3, len);
+
+ exchange.getMessage().setBody("Hello World");
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(11, len);
+
+ exchange.getMessage().setBody(List.of("A", "B", "C", "D"));
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(4, len);
+
+ exchange.getMessage().setBody(Map.of("A", 1, "B", 2, "C", 3));
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(3, len);
+
+ File f = new File("src/test/resources/log4j2.properties");
+ exchange.getMessage().setBody(f);
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(f.length(), len);
+ }
+
+ @Test
+ public void testLength() {
+ exchange.getMessage().setBody(new int[] { 4, 7, 9 });
+ Expression expression = context.resolveLanguage("csimple").createExpression("${length()}");
+ int len = expression.evaluate(exchange, int.class);
+ assertEquals(3, len);
+
+ exchange.getMessage().setBody("Hello World");
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(11, len);
+
+ exchange.getMessage().setBody(List.of("A", "BB", "CCC", "DDDD"));
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(18, len);
+
+ exchange.getMessage().setBody(Map.of("A", 1, "BB", 22, "CC", 333));
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(20, len);
+
+ File f = new File("src/test/resources/log4j2.properties");
+ exchange.getMessage().setBody(f);
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(f.length(), len);
+ }
+
@Test
public void testTrim() {
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 a05d2db62f8b..c9c573a035eb 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
@@ -72,25 +72,27 @@
"random(min,max)": { "index": 46, "kind": "function", "displayName": "Generate Random Number", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a random number between min (included) and max (excluded).", "ognl": false, "suffix": "}" },
"skip(num)": { "index": 47, "kind": "function", "displayName": "Skip First Items from the Message Body", "group": "function", "label": "function", "required": false, "javaType": "java.util.Iterator", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The skip function iterates the message body and skips the first number of items. This can be used with the Splitter EIP to split a message body and skip the first N number of [...]
"trim(exp)": { "index": 48, "kind": "function", "displayName": "Trim", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The trim function trims the message body (or expression) by removing all leading and trailing white spaces.", "ognl": false, "suffix": "}" },
- "uppercase(exp)": { "index": 49, "kind": "function", "displayName": "Uppercase", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Uppercases the message body (or expression)", "ognl": false, "suffix": "}" },
- "lowercase(exp)": { "index": 50, "kind": "function", "displayName": "Lowercase", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Lowercases the message body (or expression)", "ognl": false, "suffix": "}" },
- "concat(exp,exp,separator)": { "index": 51, "kind": "function", "displayName": "Concat", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Performs a string concat using two expressions (message body as default) with optional separator", "ognl": false, "suffix": "}" },
- "collate(num)": { "index": 52, "kind": "function", "displayName": "Group Message Body into Sub Lists", "group": "function", "label": "function", "required": false, "javaType": "java.util.Iterator", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The collate function iterates the message body and groups the data into sub lists of specified size. This can be used with the Splitter EIP to split a message body and group\/ba [...]
- "join(separator,prefix,exp)": { "index": 53, "kind": "function", "displayName": "Join", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The join function iterates the message body\/expression and joins the data into a string. The separator is by default a comma. The prefix is optional. The join uses the message body as source by default. [...]
- "messageHistory(boolean)": { "index": 54, "kind": "function", "displayName": "Print Message History", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message history of the current exchange (how it has been routed). This is similar to the route stack-trace message history the error handler logs in case of an unhandled exception. The b [...]
- "uuid(type)": { "index": 55, "kind": "function", "displayName": "Generate UUID", "group": "function", "label": "function", "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 `UuidG [...]
- "hash(exp,algorithm)": { "index": 56, "kind": "function", "displayName": "Compute Hash Value", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a hashed value (string in hex decimal) of the message body\/expression using JDK MessageDigest. The algorithm can be SHA-256 (default) or SHA3-256.", "ognl": false, "suffix": "}" },
- "empty(type)": { "index": 57, "kind": "function", "displayName": "Create Empty Object", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Creates a new empty object (decided by type). Use `string` to create an empty String. Use `list` to create an empty `java.util.ArrayList`. Use `map` to create an empty `java.util.LinkedHashMap`.", "ognl": [...]
- "iif(predicate,trueExp,falseExp)": { "index": 58, "kind": "function", "displayName": "If Then Else", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Evaluates the predicate and returns the value of trueExp or falseExp. This function is similar to the ternary operator in Java.", "ognl": false, "suffix": "}" },
- "list(val...)": { "index": 59, "kind": "function", "displayName": "Create List of values", "group": "function", "label": "function", "required": false, "javaType": "java.util.ArrayList", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The list function creates an ArrayList with the given set of values.", "ognl": false, "suffix": "}" },
- "map(key1,value1,...)": { "index": 60, "kind": "function", "displayName": "Create Map of pairs", "group": "function", "label": "function", "required": false, "javaType": "java.util.LinkedHashMap", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The map function creates a LinkedHashMap with the given set of pairs.", "ognl": false, "suffix": "}" },
- "attachments": { "index": 61, "kind": "function", "displayName": "Attachments", "group": "function", "label": "function", "required": false, "javaType": "java.util.Map", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "All the attachments as a Map<String,DataHandler.", "ognl": false, "suffix": "}" },
- "attachments.size": { "index": 62, "kind": "function", "displayName": "Attachments", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of attachments. Is 0 if there are no attachments.", "ognl": false, "suffix": "}" },
- "attachmentContentAsText": { "index": 63, "kind": "function", "displayName": "Attachment Content As Text", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the attachment as text (ie String).", "ognl": false, "suffix": "}" },
- "attachmentContent": { "index": 64, "kind": "function", "displayName": "Attachment Content", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the attachment", "ognl": false, "suffix": "}" },
- "attachmentContentAs(type)": { "index": 65, "kind": "function", "displayName": "Attachment Content As", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the attachment, converted to the given type.", "ognl": false, "suffix": "}" },
- "attachmentHeader(key,name)": { "index": 66, "kind": "function", "displayName": "Attachment Header", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The attachment header with the given name.", "ognl": false, "suffix": "}" },
- "attachmentHeader(key,name,type)": { "index": 67, "kind": "function", "displayName": "Attachment Header", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The attachment header with the given name, converted to the given type.", "ognl": false, "suffix": "}" },
- "attachment(key)": { "index": 68, "kind": "function", "displayName": "Attachment", "group": "function", "label": "function", "required": false, "javaType": "jakarta.activation.DataHandler", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The DataHandler for the given attachment.", "ognl": true, "suffix": "}" }
+ "length(exp)": { "index": 49, "kind": "function", "displayName": "Length", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The payload length (number of bytes) of the message body (or expression).", "ognl": false, "suffix": "}" },
+ "size(exp)": { "index": 50, "kind": "function", "displayName": "Size", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the message body (or expression). If the payload is java.util.Collection or java.util.Map based then the size is the number of elements; otherwise the payload size in bytes.", "ognl": false, "suffix": "}" },
+ "uppercase(exp)": { "index": 51, "kind": "function", "displayName": "Uppercase", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Uppercases the message body (or expression)", "ognl": false, "suffix": "}" },
+ "lowercase(exp)": { "index": 52, "kind": "function", "displayName": "Lowercase", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Lowercases the message body (or expression)", "ognl": false, "suffix": "}" },
+ "concat(exp,exp,separator)": { "index": 53, "kind": "function", "displayName": "Concat", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Performs a string concat using two expressions (message body as default) with optional separator", "ognl": false, "suffix": "}" },
+ "collate(num)": { "index": 54, "kind": "function", "displayName": "Group Message Body into Sub Lists", "group": "function", "label": "function", "required": false, "javaType": "java.util.Iterator", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The collate function iterates the message body and groups the data into sub lists of specified size. This can be used with the Splitter EIP to split a message body and group\/ba [...]
+ "join(separator,prefix,exp)": { "index": 55, "kind": "function", "displayName": "Join", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The join function iterates the message body\/expression and joins the data into a string. The separator is by default a comma. The prefix is optional. The join uses the message body as source by default. [...]
+ "messageHistory(boolean)": { "index": 56, "kind": "function", "displayName": "Print Message History", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message history of the current exchange (how it has been routed). This is similar to the route stack-trace message history the error handler logs in case of an unhandled exception. The b [...]
+ "uuid(type)": { "index": 57, "kind": "function", "displayName": "Generate UUID", "group": "function", "label": "function", "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 `UuidG [...]
+ "hash(exp,algorithm)": { "index": 58, "kind": "function", "displayName": "Compute Hash Value", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a hashed value (string in hex decimal) of the message body\/expression using JDK MessageDigest. The algorithm can be SHA-256 (default) or SHA3-256.", "ognl": false, "suffix": "}" },
+ "empty(type)": { "index": 59, "kind": "function", "displayName": "Create Empty Object", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Creates a new empty object (decided by type). Use `string` to create an empty String. Use `list` to create an empty `java.util.ArrayList`. Use `map` to create an empty `java.util.LinkedHashMap`.", "ognl": [...]
+ "iif(predicate,trueExp,falseExp)": { "index": 60, "kind": "function", "displayName": "If Then Else", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Evaluates the predicate and returns the value of trueExp or falseExp. This function is similar to the ternary operator in Java.", "ognl": false, "suffix": "}" },
+ "list(val...)": { "index": 61, "kind": "function", "displayName": "Create List of values", "group": "function", "label": "function", "required": false, "javaType": "java.util.ArrayList", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The list function creates an ArrayList with the given set of values.", "ognl": false, "suffix": "}" },
+ "map(key1,value1,...)": { "index": 62, "kind": "function", "displayName": "Create Map of pairs", "group": "function", "label": "function", "required": false, "javaType": "java.util.LinkedHashMap", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The map function creates a LinkedHashMap with the given set of pairs.", "ognl": false, "suffix": "}" },
+ "attachments": { "index": 63, "kind": "function", "displayName": "Attachments", "group": "function", "label": "function", "required": false, "javaType": "java.util.Map", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "All the attachments as a Map<String,DataHandler.", "ognl": false, "suffix": "}" },
+ "attachments.size": { "index": 64, "kind": "function", "displayName": "Attachments", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of attachments. Is 0 if there are no attachments.", "ognl": false, "suffix": "}" },
+ "attachmentContentAsText": { "index": 65, "kind": "function", "displayName": "Attachment Content As Text", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the attachment as text (ie String).", "ognl": false, "suffix": "}" },
+ "attachmentContent": { "index": 66, "kind": "function", "displayName": "Attachment Content", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the attachment", "ognl": false, "suffix": "}" },
+ "attachmentContentAs(type)": { "index": 67, "kind": "function", "displayName": "Attachment Content As", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the attachment, converted to the given type.", "ognl": false, "suffix": "}" },
+ "attachmentHeader(key,name)": { "index": 68, "kind": "function", "displayName": "Attachment Header", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The attachment header with the given name.", "ognl": false, "suffix": "}" },
+ "attachmentHeader(key,name,type)": { "index": 69, "kind": "function", "displayName": "Attachment Header", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The attachment header with the given name, converted to the given type.", "ognl": false, "suffix": "}" },
+ "attachment(key)": { "index": 70, "kind": "function", "displayName": "Attachment", "group": "function", "label": "function", "required": false, "javaType": "jakarta.activation.DataHandler", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The DataHandler for the given attachment.", "ognl": true, "suffix": "}" }
}
}
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 177b7bc0de58..195c7003d914 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
@@ -294,6 +294,10 @@ log sensitive data from the message itself.
|concat(exp,exp,separator) |String |Performs a string concat using two expressions (message body as default) with optional separator
+|length(exp) |int |The payload length (number of bytes) of the message body (or expression).
+
+|size(exp) |int |The size of the message body (or expression). If the payload is java.util.Collection or java.util.Map based then the size is the number of elements; otherwise the payload size in bytes.
+
|uppercase(exp) |String |Uppercases the message body (or expression)
|lowercase(exp) |String |Lowercases the message body (or expression)
diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java
index 7d0635009f83..d60d689f6d80 100644
--- a/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java
+++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java
@@ -16,9 +16,11 @@
*/
package org.apache.camel.language.csimple;
+import java.io.InputStream;
import java.lang.reflect.Array;
import java.security.MessageDigest;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -39,6 +41,7 @@ import org.apache.camel.ExpressionIllegalSyntaxException;
import org.apache.camel.InvalidPayloadException;
import org.apache.camel.Message;
import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.StreamCache;
import org.apache.camel.spi.ExchangeFormatter;
import org.apache.camel.spi.Language;
import org.apache.camel.spi.PropertiesComponent;
@@ -826,4 +829,68 @@ public final class CSimpleHelper {
return body;
}
+ public static int length(Exchange exchange, Object value) {
+ try {
+ if (value instanceof byte[] arr) {
+ return arr.length;
+ } else if (value instanceof char[] arr) {
+ return arr.length;
+ } else if (value instanceof int[] arr) {
+ return arr.length;
+ } else if (value instanceof long[] arr) {
+ return arr.length;
+ } else if (value instanceof double[] arr) {
+ return arr.length;
+ }
+
+ String data = exchange.getContext().getTypeConverter().tryConvertTo(String.class, exchange, value);
+ if (data != null) {
+ return data.length();
+ }
+ } finally {
+ if (value instanceof StreamCache streamCache) {
+ streamCache.reset();
+ }
+ }
+ return 0;
+ }
+
+ public static int size(Exchange exchange, Object value) {
+ try {
+ // calculate length
+ if (value instanceof byte[] arr) {
+ return arr.length;
+ } else if (value instanceof char[] arr) {
+ return arr.length;
+ } else if (value instanceof int[] arr) {
+ return arr.length;
+ } else if (value instanceof long[] arr) {
+ return arr.length;
+ } else if (value instanceof double[] arr) {
+ return arr.length;
+ } else if (value instanceof String s) {
+ return s.length();
+ } else if (value instanceof Collection<?> c) {
+ return c.size();
+ } else if (value instanceof Map<?, ?> m) {
+ return m.size();
+ } else {
+ // fall back to stream to read
+ InputStream is = exchange.getContext().getTypeConverter().tryConvertTo(InputStream.class, exchange, value);
+ int len = 0;
+ while (is.read() != -1) {
+ len++;
+ }
+ return len;
+ }
+ } catch (Exception e) {
+ // ignore
+ } finally {
+ if (value instanceof StreamCache streamCache) {
+ streamCache.reset();
+ }
+ }
+ return 0;
+ }
+
}
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 0f27b6b193bc..e7b56d1721e0 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
@@ -183,6 +183,12 @@ public final class SimpleConstants {
@Metadata(description = "The trim function trims the message body (or expression) by removing all leading and trailing white spaces.",
label = "function", javaType = "String", displayName = "Trim")
public static final String TRIM = "trim(exp)";
+ @Metadata(description = "The payload length (number of bytes) of the message body (or expression).",
+ label = "function", javaType = "int", displayName = "Length")
+ public static final String LENGTH = "length(exp)";
+ @Metadata(description = "The size of the message body (or expression). If the payload is java.util.Collection or java.util.Map based then the size is the number of elements; otherwise the payload size in bytes.",
+ label = "function", javaType = "int", displayName = "Size")
+ public static final String SIZE = "size(exp)";
@Metadata(description = "Uppercases the message body (or expression)",
label = "function", javaType = "String", displayName = "Uppercase")
public static final String UPPERCASE = "uppercase(exp)";
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 fcbe0675b366..f6e57d0508fd 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
@@ -23,6 +23,7 @@ import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -40,6 +41,7 @@ import org.apache.camel.ExchangePropertyKey;
import org.apache.camel.Expression;
import org.apache.camel.InvalidPayloadException;
import org.apache.camel.Predicate;
+import org.apache.camel.StreamCache;
import org.apache.camel.spi.ClassResolver;
import org.apache.camel.spi.ExchangeFormatter;
import org.apache.camel.spi.Language;
@@ -340,6 +342,138 @@ public final class SimpleExpressionBuilder {
};
}
+ /**
+ * Returns the size of the expression (number of elements in collection/map; otherwise size of payload in bytes)
+ */
+ public static Expression sizeExpression(final String expression) {
+ return new ExpressionAdapter() {
+ private Expression exp;
+
+ @Override
+ public void init(CamelContext context) {
+ if (expression != null) {
+ exp = context.resolveLanguage("simple").createExpression(expression);
+ exp.init(context);
+ }
+ }
+
+ @Override
+ public Object evaluate(Exchange exchange) {
+ Object body;
+ if (exp != null) {
+ body = exp.evaluate(exchange, Object.class);
+ } else {
+ body = exchange.getMessage().getBody(Object.class);
+ }
+ if (body != null) {
+ try {
+ // calculate length
+ if (body instanceof byte[] arr) {
+ return arr.length;
+ } else if (body instanceof char[] arr) {
+ return arr.length;
+ } else if (body instanceof int[] arr) {
+ return arr.length;
+ } else if (body instanceof long[] arr) {
+ return arr.length;
+ } else if (body instanceof double[] arr) {
+ return arr.length;
+ } else if (body instanceof String s) {
+ return s.length();
+ } else if (body instanceof Collection<?> c) {
+ return c.size();
+ } else if (body instanceof Map<?, ?> m) {
+ return m.size();
+ } else {
+ // fall back to stream to read
+ InputStream is
+ = exchange.getContext().getTypeConverter().tryConvertTo(InputStream.class, exchange, body);
+ int len = 0;
+ while (is.read() != -1) {
+ len++;
+ }
+ return len;
+ }
+ } catch (Exception e) {
+ // ignore
+ } finally {
+ if (body instanceof StreamCache streamCache) {
+ streamCache.reset();
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ if (expression != null) {
+ return "size(" + expression + ")";
+ } else {
+ return "size()";
+ }
+ }
+ };
+ }
+
+ /**
+ * Returns the length of the expression (length of payload in bytes)
+ */
+ public static Expression lengthExpression(final String expression) {
+ return new ExpressionAdapter() {
+ private Expression exp;
+
+ @Override
+ public void init(CamelContext context) {
+ if (expression != null) {
+ exp = context.resolveLanguage("simple").createExpression(expression);
+ exp.init(context);
+ }
+ }
+
+ @Override
+ public Object evaluate(Exchange exchange) {
+ Object body;
+ if (exp != null) {
+ body = exp.evaluate(exchange, Object.class);
+ } else {
+ body = exchange.getMessage().getBody(Object.class);
+ }
+ try {
+ if (body instanceof byte[] arr) {
+ return arr.length;
+ } else if (body instanceof char[] arr) {
+ return arr.length;
+ } else if (body instanceof int[] arr) {
+ return arr.length;
+ } else if (body instanceof long[] arr) {
+ return arr.length;
+ } else if (body instanceof double[] arr) {
+ return arr.length;
+ }
+ String data = exchange.getContext().getTypeConverter().tryConvertTo(String.class, exchange, body);
+ if (data != null) {
+ return data.length();
+ }
+ } finally {
+ if (body instanceof StreamCache streamCache) {
+ streamCache.reset();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ if (expression != null) {
+ return "length(" + expression + ")";
+ } else {
+ return "length()";
+ }
+ }
+ };
+ }
+
/**
* A ternary condition expression
*/
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 923a5bd2b9c9..6e9de342be52 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
@@ -911,6 +911,27 @@ public class SimpleFunctionExpression extends LiteralExpression {
return SimpleExpressionBuilder.lowercaseExpression(exp);
}
+ // length function
+ remainder = ifStartsWithReturnRemainder("length(", function);
+ if (remainder != null) {
+ String exp = null;
+ String value = StringHelper.before(remainder, ")");
+ if (ObjectHelper.isNotEmpty(value)) {
+ exp = StringHelper.removeQuotes(value);
+ }
+ return SimpleExpressionBuilder.lengthExpression(exp);
+ }
+ // size function
+ remainder = ifStartsWithReturnRemainder("size(", function);
+ if (remainder != null) {
+ String exp = null;
+ String value = StringHelper.before(remainder, ")");
+ if (ObjectHelper.isNotEmpty(value)) {
+ exp = StringHelper.removeQuotes(value);
+ }
+ return SimpleExpressionBuilder.sizeExpression(exp);
+ }
+
// messageHistory function
remainder = ifStartsWithReturnRemainder("messageHistory", function);
if (remainder != null) {
@@ -2076,6 +2097,55 @@ public class SimpleFunctionExpression extends LiteralExpression {
return "Object o = " + exp + ";\n return lowercase(exchange, o);";
}
+ // length function
+ remainder = ifStartsWithReturnRemainder("length(", function);
+ if (remainder != null) {
+ String exp = null;
+ String values = StringHelper.beforeLast(remainder, ")");
+ if (ObjectHelper.isNotEmpty(values)) {
+ String[] tokens = codeSplitSafe(values, ',', true, true);
+ if (tokens.length != 1) {
+ throw new SimpleParserException(
+ "Valid syntax: ${length(exp)} was: " + function, token.getIndex());
+ }
+ // single quotes should be double quotes
+ String s = tokens[0];
+ if (StringHelper.isSingleQuoted(s)) {
+ s = StringHelper.removeLeadingAndEndingQuotes(s);
+ s = StringQuoteHelper.doubleQuote(s);
+ }
+ exp = s;
+ }
+ if (ObjectHelper.isEmpty(exp)) {
+ exp = "body";
+ }
+ return "Object o = " + exp + ";\n return length(exchange, o);";
+ }
+ // size function
+ remainder = ifStartsWithReturnRemainder("size(", function);
+ if (remainder != null) {
+ String exp = null;
+ String values = StringHelper.beforeLast(remainder, ")");
+ if (ObjectHelper.isNotEmpty(values)) {
+ String[] tokens = codeSplitSafe(values, ',', true, true);
+ if (tokens.length != 1) {
+ throw new SimpleParserException(
+ "Valid syntax: ${size(exp)} was: " + function, token.getIndex());
+ }
+ // single quotes should be double quotes
+ String s = tokens[0];
+ if (StringHelper.isSingleQuoted(s)) {
+ s = StringHelper.removeLeadingAndEndingQuotes(s);
+ s = StringQuoteHelper.doubleQuote(s);
+ }
+ exp = s;
+ }
+ if (ObjectHelper.isEmpty(exp)) {
+ exp = "body";
+ }
+ return "Object o = " + exp + ";\n return size(exchange, o);";
+ }
+
// collate function
remainder = ifStartsWithReturnRemainder("collate(", function);
if (remainder != null) {
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 553f38e64241..b64005c64f81 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
@@ -2419,6 +2419,56 @@ public class SimpleTest extends LanguageTestSupport {
assertEquals(expected, s);
}
+ @Test
+ public void testSize() {
+ exchange.getMessage().setBody(new int[] { 4, 7, 9 });
+ Expression expression = context.resolveLanguage("simple").createExpression("${size()}");
+ int len = expression.evaluate(exchange, int.class);
+ assertEquals(3, len);
+
+ exchange.getMessage().setBody("Hello World");
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(11, len);
+
+ exchange.getMessage().setBody(List.of("A", "B", "C", "D"));
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(4, len);
+
+ exchange.getMessage().setBody(Map.of("A", 1, "B", 2, "C", 3));
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(3, len);
+
+ File f = new File("src/test/resources/log4j2.properties");
+ exchange.getMessage().setBody(f);
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(f.length(), len);
+ }
+
+ @Test
+ public void testLength() {
+ exchange.getMessage().setBody(new int[] { 4, 7, 9 });
+ Expression expression = context.resolveLanguage("simple").createExpression("${length()}");
+ int len = expression.evaluate(exchange, int.class);
+ assertEquals(3, len);
+
+ exchange.getMessage().setBody("Hello World");
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(11, len);
+
+ exchange.getMessage().setBody(List.of("A", "BB", "CCC", "DDDD"));
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(18, len);
+
+ exchange.getMessage().setBody(Map.of("A", 1, "BB", 22, "CC", 333));
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(20, len);
+
+ File f = new File("src/test/resources/log4j2.properties");
+ exchange.getMessage().setBody(f);
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(f.length(), len);
+ }
+
@Test
public void testTrim() {
exchange.getMessage().setBody(" Hello World ");