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 5c7e11efdf65 camel-core - simple languge improve docs and adjust
size/length functions
5c7e11efdf65 is described below
commit 5c7e11efdf6515da34a22fa3cf2dfd0f4c962421
Author: Claus Ibsen <[email protected]>
AuthorDate: Sun Jan 25 12:06:48 2026 +0100
camel-core - simple languge improve docs and adjust size/length functions
---
.../org/apache/camel/catalog/languages/simple.json | 8 +-
.../language/csimple/joor/OriginalSimpleTest.java | 34 +++++---
.../org/apache/camel/language/simple/simple.json | 8 +-
.../modules/languages/pages/simple-language.adoc | 46 +++++++++--
.../camel/language/csimple/CSimpleHelper.java | 49 ++++++------
.../camel/language/simple/SimpleConstants.java | 11 ++-
.../language/simple/SimpleExpressionBuilder.java | 90 +++++++++++-----------
.../apache/camel/language/simple/SimpleTest.java | 33 +++++---
8 files changed, 177 insertions(+), 102 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 b2dc86943096..347fe36b5013 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
@@ -33,7 +33,7 @@
"attachmentsHeader(key,name)": { "index": 6, "kind": "function",
"displayName": "Attachments 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": "}" },
"attachmentsHeaderAs(key,name,type)": { "index": 7, "kind": "function",
"displayName": "Attachments Header As", "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": "}" },
"attachmentsSize": { "index": 8, "kind": "function", "displayName":
"Attachments Size", "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": "}" },
- "average(val...)": { "index": 9, "kind": "function", "displayName":
"Average Number", "group": "function", "label": "function", "required": false,
"javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the average number
from all the values", "ognl": false, "suffix": "}" },
+ "average(val...)": { "index": 9, "kind": "function", "displayName":
"Average Number", "group": "function", "label": "function", "required": false,
"javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the average number
from all the values (integral numbers only).", "ognl": false, "suffix": "}" },
"base64Decode(exp)": { "index": 10, "kind": "function", "displayName":
"Base64 Decode", "group": "function", "label": "function", "required": false,
"javaType": "byte[]", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Base64 decodes the
message body (or expression)", "ognl": false, "suffix": "}" },
"base64Encode(exp)": { "index": 11, "kind": "function", "displayName":
"Base64 Encode", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Base64 encodes the
message body (or expression)", "ognl": false, "suffix": "}" },
"bean(name.method)": { "index": 12, "kind": "function", "displayName":
"Call Java Bean", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Calls a Java bean. The
name of the bean can also refer to a class name using type prefix as follows
`bean:type:com.foo.MyClass`. If no method name is given then Camel will
automatic attempt to find the b [...]
@@ -81,11 +81,11 @@
"lowercase(exp)": { "index": 54, "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": "}" },
"mandatoryBodyAs(type)": { "index": 55, "kind": "function", "displayName":
"Mandatory Body As", "group": "function", "label": "function", "required":
false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Converts the message body to the given type (classname). If the body is null
then the function will fail with an exception", "ognl": true, "suffix": "}" },
"map(key1,value1,...)": { "index": 56, "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": "}" },
- "max(val...)": { "index": 57, "kind": "function", "displayName": "Maximum
Number", "group": "function", "label": "function", "required": false,
"javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the maximum number
from all the values", "ognl": false, "suffix": "}" },
+ "max(val...)": { "index": 57, "kind": "function", "displayName": "Maximum
Number", "group": "function", "label": "function", "required": false,
"javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the maximum number
from all the values (integral numbers only).", "ognl": false, "suffix": "}" },
"messageAs(type)": { "index": 58, "kind": "function", "displayName":
"Message As", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Converts the message
to the given type (classname).", "ognl": true, "suffix": "}" },
"messageHistory(boolean)": { "index": 59, "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 [...]
"messageTimestamp": { "index": 60, "kind": "function", "displayName":
"Message Timestamp", "group": "function", "label": "function", "required":
false, "javaType": "long", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
message timestamp (millis since epoc) that this message originates from. Some
systems like JMS, Kafka, AWS have a timestamp on the event\/message that Camel
received. This method returns the timestam [...]
- "min(val...)": { "index": 61, "kind": "function", "displayName": "Minimum
Number", "group": "function", "label": "function", "required": false,
"javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the minimum number
from all the values", "ognl": false, "suffix": "}" },
+ "min(val...)": { "index": 61, "kind": "function", "displayName": "Minimum
Number", "group": "function", "label": "function", "required": false,
"javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the minimum number
from all the values (integral numbers only).", "ognl": false, "suffix": "}" },
"newEmpty(type)": { "index": 62, "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`. Use `s [...]
"not": { "index": 63, "kind": "function", "displayName": "Not", "group":
"function", "label": "function", "required": false, "javaType": "boolean",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "Evaluates the predicate and returns the
opposite.", "ognl": false, "suffix": "}" },
"null": { "index": 64, "kind": "function", "displayName": "Null", "group":
"function", "label": "function", "required": false, "javaType": "Object",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "Represents a null value", "ognl": false,
"suffix": "}" },
@@ -104,7 +104,7 @@
"setHeader(name,type,exp)": { "index": 77, "kind": "function",
"displayName": "Set Header", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sets a message header with the given expression (optional converting to the
given type)", "ognl": false, "suffix": "}" },
"setVariable(name,type,exp)": { "index": 78, "kind": "function",
"displayName": "Set Variable", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sets a variable with the given expression (optional converting to the given
type)", "ognl": false, "suffix": "}" },
"shuffle(val...)": { "index": 79, "kind": "function", "displayName":
"Shuffle Values", "group": "function", "label": "function", "required": false,
"javaType": "List", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a list of all the
values shuffled in random order", "ognl": false, "suffix": "}" },
- "size(exp)": { "index": 80, "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": "}" },
+ "size(exp)": { "index": 80, "kind": "function", "displayName": "Size",
"group": "function", "label": "function", "required": false, "javaType": "int",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "Returns the number of elements in collection
or array based payloads. If the value is null then 0 is returned, otherwise
1.", "ognl": false, "suffix": "}" },
"skip(num)": { "index": 81, "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 [...]
"split(exp,separator)": { "index": 82, "kind": "function", "displayName":
"Split String Values", "group": "function", "label": "function", "required":
false, "javaType": "String[]", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Splits the message body\/expression as a String value using the separator into
a String array", "ognl": false, "suffix": "}" },
"stepId": { "index": 83, "kind": "function", "displayName": "Step Id",
"group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the id of the
current step the Exchange is being routed.", "ognl": false, "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 192be8370c8c..cb0398c87d50 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
@@ -43,6 +43,7 @@ import org.apache.camel.ExpressionIllegalSyntaxException;
import org.apache.camel.InvalidPayloadException;
import org.apache.camel.Predicate;
import org.apache.camel.component.bean.MethodNotFoundException;
+import org.apache.camel.converter.stream.FileInputStreamCache;
import org.apache.camel.language.bean.RuntimeBeanExpressionException;
import org.apache.camel.language.csimple.CSimpleLanguage;
import org.apache.camel.language.simple.SimpleTest;
@@ -2373,25 +2374,29 @@ public class OriginalSimpleTest extends
LanguageTestSupport {
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);
+ int size = expression.evaluate(exchange, int.class);
+ assertEquals(3, size);
exchange.getMessage().setBody("Hello World");
- len = expression.evaluate(exchange, int.class);
- assertEquals(11, len);
+ size = expression.evaluate(exchange, int.class);
+ assertEquals(1, size);
+
+ exchange.getMessage().setBody(null);
+ size = expression.evaluate(exchange, int.class);
+ assertEquals(0, size);
exchange.getMessage().setBody(List.of("A", "B", "C", "D"));
- len = expression.evaluate(exchange, int.class);
- assertEquals(4, len);
+ size = expression.evaluate(exchange, int.class);
+ assertEquals(4, size);
exchange.getMessage().setBody(Map.of("A", 1, "B", 2, "C", 3));
- len = expression.evaluate(exchange, int.class);
- assertEquals(3, len);
+ size = expression.evaluate(exchange, int.class);
+ assertEquals(3, size);
File f = new File("src/test/resources/log4j2.properties");
exchange.getMessage().setBody(f);
- len = expression.evaluate(exchange, int.class);
- assertEquals(f.length(), len);
+ size = expression.evaluate(exchange, int.class);
+ assertEquals(1, size);
}
@Test
@@ -2417,6 +2422,11 @@ public class OriginalSimpleTest extends
LanguageTestSupport {
exchange.getMessage().setBody(f);
len = expression.evaluate(exchange, int.class);
assertEquals(f.length(), len);
+
+ FileInputStreamCache fis = new FileInputStreamCache(f);
+ exchange.getMessage().setBody(fis);
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(f.length(), len);
}
@Test
@@ -2959,6 +2969,10 @@ public class OriginalSimpleTest extends
LanguageTestSupport {
Integer i = expression.evaluate(exchange, Integer.class);
assertEquals(987, i);
+ expression =
context.resolveLanguage("simple").createExpression("${abs(-5)}");
+ i = expression.evaluate(exchange, Integer.class);
+ assertEquals(5, i);
+
expression =
context.resolveLanguage("csimple").createExpression("${abs(${body})}");
String s = expression.evaluate(exchange, String.class);
assertEquals("987", s);
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 b2dc86943096..347fe36b5013 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
@@ -33,7 +33,7 @@
"attachmentsHeader(key,name)": { "index": 6, "kind": "function",
"displayName": "Attachments 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": "}" },
"attachmentsHeaderAs(key,name,type)": { "index": 7, "kind": "function",
"displayName": "Attachments Header As", "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": "}" },
"attachmentsSize": { "index": 8, "kind": "function", "displayName":
"Attachments Size", "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": "}" },
- "average(val...)": { "index": 9, "kind": "function", "displayName":
"Average Number", "group": "function", "label": "function", "required": false,
"javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the average number
from all the values", "ognl": false, "suffix": "}" },
+ "average(val...)": { "index": 9, "kind": "function", "displayName":
"Average Number", "group": "function", "label": "function", "required": false,
"javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the average number
from all the values (integral numbers only).", "ognl": false, "suffix": "}" },
"base64Decode(exp)": { "index": 10, "kind": "function", "displayName":
"Base64 Decode", "group": "function", "label": "function", "required": false,
"javaType": "byte[]", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Base64 decodes the
message body (or expression)", "ognl": false, "suffix": "}" },
"base64Encode(exp)": { "index": 11, "kind": "function", "displayName":
"Base64 Encode", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Base64 encodes the
message body (or expression)", "ognl": false, "suffix": "}" },
"bean(name.method)": { "index": 12, "kind": "function", "displayName":
"Call Java Bean", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Calls a Java bean. The
name of the bean can also refer to a class name using type prefix as follows
`bean:type:com.foo.MyClass`. If no method name is given then Camel will
automatic attempt to find the b [...]
@@ -81,11 +81,11 @@
"lowercase(exp)": { "index": 54, "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": "}" },
"mandatoryBodyAs(type)": { "index": 55, "kind": "function", "displayName":
"Mandatory Body As", "group": "function", "label": "function", "required":
false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Converts the message body to the given type (classname). If the body is null
then the function will fail with an exception", "ognl": true, "suffix": "}" },
"map(key1,value1,...)": { "index": 56, "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": "}" },
- "max(val...)": { "index": 57, "kind": "function", "displayName": "Maximum
Number", "group": "function", "label": "function", "required": false,
"javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the maximum number
from all the values", "ognl": false, "suffix": "}" },
+ "max(val...)": { "index": 57, "kind": "function", "displayName": "Maximum
Number", "group": "function", "label": "function", "required": false,
"javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the maximum number
from all the values (integral numbers only).", "ognl": false, "suffix": "}" },
"messageAs(type)": { "index": 58, "kind": "function", "displayName":
"Message As", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Converts the message
to the given type (classname).", "ognl": true, "suffix": "}" },
"messageHistory(boolean)": { "index": 59, "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 [...]
"messageTimestamp": { "index": 60, "kind": "function", "displayName":
"Message Timestamp", "group": "function", "label": "function", "required":
false, "javaType": "long", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
message timestamp (millis since epoc) that this message originates from. Some
systems like JMS, Kafka, AWS have a timestamp on the event\/message that Camel
received. This method returns the timestam [...]
- "min(val...)": { "index": 61, "kind": "function", "displayName": "Minimum
Number", "group": "function", "label": "function", "required": false,
"javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the minimum number
from all the values", "ognl": false, "suffix": "}" },
+ "min(val...)": { "index": 61, "kind": "function", "displayName": "Minimum
Number", "group": "function", "label": "function", "required": false,
"javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the minimum number
from all the values (integral numbers only).", "ognl": false, "suffix": "}" },
"newEmpty(type)": { "index": 62, "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`. Use `s [...]
"not": { "index": 63, "kind": "function", "displayName": "Not", "group":
"function", "label": "function", "required": false, "javaType": "boolean",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "Evaluates the predicate and returns the
opposite.", "ognl": false, "suffix": "}" },
"null": { "index": 64, "kind": "function", "displayName": "Null", "group":
"function", "label": "function", "required": false, "javaType": "Object",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "Represents a null value", "ognl": false,
"suffix": "}" },
@@ -104,7 +104,7 @@
"setHeader(name,type,exp)": { "index": 77, "kind": "function",
"displayName": "Set Header", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sets a message header with the given expression (optional converting to the
given type)", "ognl": false, "suffix": "}" },
"setVariable(name,type,exp)": { "index": 78, "kind": "function",
"displayName": "Set Variable", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Sets a variable with the given expression (optional converting to the given
type)", "ognl": false, "suffix": "}" },
"shuffle(val...)": { "index": 79, "kind": "function", "displayName":
"Shuffle Values", "group": "function", "label": "function", "required": false,
"javaType": "List", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a list of all the
values shuffled in random order", "ognl": false, "suffix": "}" },
- "size(exp)": { "index": 80, "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": "}" },
+ "size(exp)": { "index": 80, "kind": "function", "displayName": "Size",
"group": "function", "label": "function", "required": false, "javaType": "int",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "Returns the number of elements in collection
or array based payloads. If the value is null then 0 is returned, otherwise
1.", "ognl": false, "suffix": "}" },
"skip(num)": { "index": 81, "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 [...]
"split(exp,separator)": { "index": 82, "kind": "function", "displayName":
"Split String Values", "group": "function", "label": "function", "required":
false, "javaType": "String[]", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Splits the message body\/expression as a String value using the separator into
a String array", "ognl": false, "suffix": "}" },
"stepId": { "index": 83, "kind": "function", "displayName": "Step Id",
"group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns the id of the
current step the Exchange is being routed.", "ognl": false, "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 fb25c08d3519..91dba89d7fa8 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
@@ -349,22 +349,58 @@ This will get the `Date` object from the header with key
birthday, and format th
|Function |Response Type |Description
|`abs()` | `long` | Converts the message body to a long number and return the
absolute value.
|`abs(exp)` | `Long` | Converts the message body (or expression) to a long
number and return the absolute value.
-|`average(val1,val2,...)` | `long` | Returns the average number from all the
values.
+|`average(val1,val2,...)` | `long` | Returns the average number from all the
values (integral numbers only).
|`ceil()` | `int` | Converts the message body to a floating number and return
the ceil value (rounded up to nearest integer).
|`ceil(exp)` | `int` | Converts the expression to a floating number and return
the ceil value (rounded up to nearest integer).
|`floor()` | `int` | Converts the message body to a floating number and return
the floor value (rounded down to nearest integer).
|`floor(exp)` | `int` | Converts the expression to a floating number and
return the floor value (rounded down to nearest integer).
|`length()` | `int` | The payload length (number of bytes) of the message body
|`length(exp)` | `int` | The payload length (number of bytes) of the
expression.
-|`max(val1,val2,...)` | `long` | Returns the maximum number from all the
values.
-|`min(val1,val2,...)` | `long` | Returns the minimum number from all the
values.
+|`max(val1,val2,...)` | `long` | Returns the maximum number from all the
values (integral numbers only).
+|`min(val1,val2,...)` | `long` | Returns the minimum number from all the
values (integral numbers only).
|`random(max)` | `int` | Returns a random `Integer` between 0 (included) and
max (excluded).
|`random(min,max)` | `int` | Returns a random `Integer` between min (included)
and max (excluded),
-|`size()` | `int` | The size of the message body. 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.
-|`size(exp)` | `int` | The size of the 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.
+|`size()` | `int` | Returns the number of elements in collection or array
based message body. If the value is null then 0 is returned, otherwise 1.
+|`size(exp)` | `int` | Returns the number of elements in collection or array
based value. If the value is null then 0 is returned, otherwise 1.
|`sum(val1,val2,...)` | `long` | Sums together all the values as integral
numbers. This function can also be used to subtract by using negative numbers.
|====
+The `abs` function returns the absolute value of a numeric value. It converts
the input (either the message body or the result of an expression) to a long
number and computes its absolute value.
+A few examples `${abs(-5)}` returns `5`, and `${abs(5)}` also returns `5`.
+
+The `average` function calculates the average (mean) of integral numbers (not
floating point).
+Assume message body is `[10, 20, 30]` (as `List<Integer>` or similar) then
`${avg()}` results in `20`
+
+The `ceil` functions returns the value of number rounded up to the nearest
integer that is greater than or equal to number.
+For example `${ceil(5.7)}` returns `6`, and `${ceil(5.1)}` also returns `6`.
+
+The `floor` functions returns the value of number rounded down to the nearest
integer that is smaller or equal to number.
+For example `${ceil(5.7)}` returns `5`, and `${ceil(5.1)}` also returns `5`.
+
+The `length` function calculates the payload size in bytes (if possible). This
is calculated by
+(if necessary) converting the payload into String to use for determine the
byte length.
+For example `${length('Hello World')}` returns `11`. For larger payloads, then
when using xref:manual::stream-caching.adoc[stream caching]
+the length is pre-computed and usually does not require to load the content
into memory.
+
+The `max` and `min` functions in are used to find the maximum or minimum value
among a set of numeric integral values.
+For example message body contains a list `[10, 5, 30, 15]` then `${max()}`
returns `30` and `${min()}` returns `5`.
+
+The `random` functions returns a random number between min and max (exclusive).
+For example `${random(10)}` returns a random number 0..9. And
`${random(18,50)}` returns a random number between 18..49.
+
+The `size` functions is used to determine the number of elements, when using
`Collection` or array based payloads.
+If not then either 0 or 1 is returned whether the body is `null` or not.
+For example if the message body contains a `List` with 7 elements then
`${size()}` returns `7`.
+On the other hand if the message body contains a `InputStream` then the result
is `1`, and when body is `null` then `0` is returned.
+And for String payloads such as `${size('Hello World')}` then `1` is always
returned.
+
+TIP: Use the `length` function to return the payload length in bytes.
+
+The `sum` function adds up numeric values (not floating point) and returns the
result as a long.
+Assume message body is `[10, 20, 30]` (as `List<Integer>` or similar) then
`${sum()}` results in `60`
+You can also use the `sum` function to add or subtract numbers. For example if
you want to add 2 to a number, you can do
+`$sum($\{body},2)}`, and likewise to subtract you use negative number, such as
`$sum($\{body},-2)}`.
+
=== Other Functions
[width="100%",cols="10%,10%,80%",options="header",]
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 902de3f38451..146b288bb423 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
@@ -56,6 +56,7 @@ import org.apache.camel.support.GroupIterator;
import org.apache.camel.support.LanguageHelper;
import org.apache.camel.support.MessageHelper;
import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.IOHelper;
import org.apache.camel.util.InetAddressUtil;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.OgnlHelper;
@@ -1130,11 +1131,28 @@ public final class CSimpleHelper {
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();
+ } else if (value instanceof StreamCache sc) {
+ return (int) sc.length();
+ } else {
+ // first read as stream
+ InputStream is = null;
+ try {
+ is =
exchange.getContext().getTypeConverter().tryConvertTo(InputStream.class,
exchange, value);
+ int len = 0;
+ while (is.read() != -1) {
+ len++;
+ }
+ return len;
+ } catch (Exception e) {
+ // ignore
+ } finally {
+ IOHelper.close(is);
+ }
+ // fallback to use string based
+ String data =
exchange.getContext().getTypeConverter().tryConvertTo(String.class, exchange,
value);
+ if (data != null) {
+ return data.length();
+ }
}
} finally {
if (value instanceof StreamCache streamCache) {
@@ -1145,8 +1163,7 @@ public final class CSimpleHelper {
}
public static int size(Exchange exchange, Object value) {
- try {
- // calculate length
+ if (value != null) {
if (value instanceof byte[] arr) {
return arr.length;
} else if (value instanceof char[] arr) {
@@ -1157,26 +1174,14 @@ public final class CSimpleHelper {
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 String[] arr) {
+ return arr.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 1;
}
}
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 0e12b00e0ff3..17e29b65ba4b 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
@@ -53,7 +53,8 @@ public final class SimpleConstants {
label = "function")
public static final String ATTACHMENTS_SIZE = "attachmentsSize";
- @Metadata(description = "Returns the average number from all the values",
label = "function", javaType = "long",
+ @Metadata(description = "Returns the average number from all the values
(integral numbers only).", label = "function",
+ javaType = "long",
displayName = "Average Number")
public static final String AVERAGE = "average(val...)";
@@ -233,7 +234,8 @@ public final class SimpleConstants {
javaType = "java.util.LinkedHashMap", displayName = "Create Map
of pairs")
public static final String MAP = "map(key1,value1,...)";
- @Metadata(description = "Returns the maximum number from all the values",
label = "function", javaType = "long",
+ @Metadata(description = "Returns the maximum number from all the values
(integral numbers only).", label = "function",
+ javaType = "long",
displayName = "Maximum Number")
public static final String MAX = "max(val...)";
@@ -248,7 +250,8 @@ public final class SimpleConstants {
javaType = "long", label = "function")
public static final String MESSAGE_TIMESTAMP = "messageTimestamp";
- @Metadata(description = "Returns the minimum number from all the values",
label = "function", javaType = "long",
+ @Metadata(description = "Returns the minimum number from all the values
(integral numbers only).", label = "function",
+ javaType = "long",
displayName = "Minimum Number")
public static final String MIN = "min(val...)";
@@ -322,7 +325,7 @@ public final class SimpleConstants {
label = "function", javaType = "List", displayName = "Shuffle
Values")
public static final String SHUFFLE = "shuffle(val...)";
- @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.",
+ @Metadata(description = "Returns the number of elements in collection or
array based payloads. If the value is null then 0 is returned, otherwise 1.",
label = "function", javaType = "int", displayName = "Size")
public static final String SIZE = "size(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 debbc4c9e813..bf914121cb7e 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
@@ -400,7 +400,7 @@ public final class SimpleExpressionBuilder {
if (exp != null) {
body = exp.evaluate(exchange, Object.class);
} else {
- body = exchange.getMessage().getBody(Object.class);
+ body = exchange.getMessage().getBody();
}
// this may be an object that we can iterate
Iterable<?> it =
org.apache.camel.support.ObjectHelper.createIterable(body);
@@ -954,7 +954,7 @@ public final class SimpleExpressionBuilder {
}
/**
- * Returns the size of the expression (number of elements in
collection/map; otherwise size of payload in bytes)
+ * Returns the size of the expression (number of elements in
collection/map; otherwise 1)
*/
public static Expression sizeExpression(final String expression) {
return new ExpressionAdapter() {
@@ -974,46 +974,30 @@ public final class SimpleExpressionBuilder {
if (exp != null) {
body = exp.evaluate(exchange, Object.class);
} else {
- body = exchange.getMessage().getBody(Object.class);
+ body = exchange.getMessage().getBody();
}
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();
- }
+ 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[] arr) {
+ return arr.length;
+ } else if (body instanceof Collection<?> c) {
+ return c.size();
+ } else if (body instanceof Map<?, ?> m) {
+ return m.size();
+ } else {
+ return 1;
}
}
- return null;
+ return 0;
}
@Override
@@ -1048,7 +1032,7 @@ public final class SimpleExpressionBuilder {
if (exp != null) {
body = exp.evaluate(exchange, Object.class);
} else {
- body = exchange.getMessage().getBody(Object.class);
+ body = exchange.getMessage().getBody();
}
try {
if (body instanceof byte[] arr) {
@@ -1061,10 +1045,30 @@ public final class SimpleExpressionBuilder {
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();
+ } else if (body instanceof String[] arr) {
+ return arr.length;
+ } else if (body instanceof StreamCache sc) {
+ return (int) sc.length();
+ } else {
+ // first read as stream
+ InputStream is = null;
+ try {
+ is =
exchange.getContext().getTypeConverter().tryConvertTo(InputStream.class,
exchange, body);
+ int len = 0;
+ while (is.read() != -1) {
+ len++;
+ }
+ return len;
+ } catch (Exception e) {
+ // ignore
+ } finally {
+ IOHelper.close(is);
+ }
+ // fallback to use string based
+ String data =
exchange.getContext().getTypeConverter().tryConvertTo(String.class, exchange,
body);
+ if (data != null) {
+ return data.length();
+ }
}
} finally {
if (body instanceof StreamCache streamCache) {
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 fbb31a78266a..606a0482aa71 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
@@ -2607,25 +2607,29 @@ public class SimpleTest extends LanguageTestSupport {
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);
+ int size = expression.evaluate(exchange, int.class);
+ assertEquals(3, size);
exchange.getMessage().setBody("Hello World");
- len = expression.evaluate(exchange, int.class);
- assertEquals(11, len);
+ size = expression.evaluate(exchange, int.class);
+ assertEquals(1, size);
+
+ exchange.getMessage().setBody(null);
+ size = expression.evaluate(exchange, int.class);
+ assertEquals(0, size);
exchange.getMessage().setBody(List.of("A", "B", "C", "D"));
- len = expression.evaluate(exchange, int.class);
- assertEquals(4, len);
+ size = expression.evaluate(exchange, int.class);
+ assertEquals(4, size);
exchange.getMessage().setBody(Map.of("A", 1, "B", 2, "C", 3));
- len = expression.evaluate(exchange, int.class);
- assertEquals(3, len);
+ size = expression.evaluate(exchange, int.class);
+ assertEquals(3, size);
File f = new File("src/test/resources/log4j2.properties");
exchange.getMessage().setBody(f);
- len = expression.evaluate(exchange, int.class);
- assertEquals(f.length(), len);
+ size = expression.evaluate(exchange, int.class);
+ assertEquals(1, size);
}
@Test
@@ -2651,6 +2655,11 @@ public class SimpleTest extends LanguageTestSupport {
exchange.getMessage().setBody(f);
len = expression.evaluate(exchange, int.class);
assertEquals(f.length(), len);
+
+ FileInputStreamCache fis = new FileInputStreamCache(f);
+ exchange.getMessage().setBody(fis);
+ len = expression.evaluate(exchange, int.class);
+ assertEquals(f.length(), len);
}
@Test
@@ -3256,6 +3265,10 @@ public class SimpleTest extends LanguageTestSupport {
Integer i = expression.evaluate(exchange, Integer.class);
assertEquals(987, i);
+ expression =
context.resolveLanguage("simple").createExpression("${abs(-5)}");
+ i = expression.evaluate(exchange, Integer.class);
+ assertEquals(5, i);
+
expression =
context.resolveLanguage("simple").createExpression("${abs(${body})}");
String s = expression.evaluate(exchange, String.class);
assertEquals("987", s);