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 1affbd5dd7b0 camel-core - Add range function to simple language
1affbd5dd7b0 is described below

commit 1affbd5dd7b0a938317c7ac02ed5463e176bcfa2
Author: Claus Ibsen <[email protected]>
AuthorDate: Sun Feb 8 12:36:28 2026 +0100

    camel-core - Add range function to simple language
---
 .../org/apache/camel/catalog/languages/simple.json | 67 +++++++++++-----------
 .../language/csimple/joor/OriginalSimpleTest.java  | 12 ++++
 .../org/apache/camel/language/simple/simple.json   | 67 +++++++++++-----------
 .../modules/languages/pages/simple-language.adoc   |  7 ++-
 .../camel/language/csimple/CSimpleHelper.java      | 13 +++++
 .../camel/language/simple/SimpleConstants.java     |  4 ++
 .../language/simple/SimpleExpressionBuilder.java   | 37 ++++++++++++
 .../simple/ast/SimpleFunctionExpression.java       | 39 +++++++++++++
 .../apache/camel/language/simple/SimpleTest.java   | 12 ++++
 .../java/org/apache/camel/util/SimpleUtils.java    |  1 +
 10 files changed, 192 insertions(+), 67 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 49cbec39c26a..e1bc7744aff8 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
@@ -104,38 +104,39 @@
     "propertiesExist:key": { "index": 76, "kind": "function", "displayName": 
"Property Placeholder Exists", "group": "core", "label": "core", "required": 
false, "javaType": "boolean", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Checks whether a property placeholder with the given key exists or not. The 
result can be negated by prefixing the key with !", "ognl": false, "suffix": 
"}" },
     "quote(exp)": { "index": 77, "kind": "function", "displayName": "Quote", 
"group": "string", "label": "string", "required": false, "javaType": "String", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Returns the message body (or expression) as a 
double quoted string", "ognl": false, "suffix": "}" },
     "random(min,max)": { "index": 78, "kind": "function", "displayName": 
"Random", "group": "number", "label": "number", "required": false, "javaType": 
"int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Returns a random number between min and 
max (exclusive)", "ognl": false, "suffix": "}" },
-    "ref:name": { "index": 79, "kind": "function", "displayName": "Bean By 
Id", "group": "core", "label": "core", "required": false, "javaType": "Object", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "To look up a bean from the Registry with the 
given name.", "ognl": false, "suffix": "}" },
-    "replace(from,to,exp)": { "index": 80, "kind": "function", "displayName": 
"Replace String Values", "group": "string", "label": "string", "required": 
false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Replace all the string values in the message body\/expression. To make it 
easier to replace single and double quotes, then you can use XML escaped values 
`\\&quot;` as double quote, `\\&apos;` as s [...]
-    "reverse(val...)": { "index": 81, "kind": "function", "displayName": 
"Reverse Values", "group": "collection", "label": "collection", "required": 
false, "javaType": "List", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a list of all the values, but in reverse order", "ognl": false, 
"suffix": "}" },
-    "routeGroup": { "index": 82, "kind": "function", "displayName": "Route 
Group", "group": "core", "label": "core", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The route group of the 
current route the Exchange is being routed. Not all routes have a group 
assigned, so this may be null.", "ognl": false, "suffix": "}" },
-    "routeId": { "index": 83, "kind": "function", "displayName": "Route Id", 
"group": "core", "label": "core", "required": false, "javaType": "String", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The route id of the current route the Exchange 
is being routed", "ognl": false, "suffix": "}" },
-    "safeQuote(exp)": { "index": 84, "kind": "function", "displayName": "Safe 
Quote", "group": "string", "label": "string", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the message body 
(or expression) safely quoted if needed", "ognl": false, "suffix": "}" },
-    "setVariable(key,exp)": { "index": 85, "kind": "function", "displayName": 
"Set Variable", "group": "attachment", "label": "attachment", "required": 
false, "javaType": "Object", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Sets an attachment with payload from the message body\/expression.", "ognl": 
false, "suffix": "}" },
-    "setHeader(name,type,exp)": { "index": 86, "kind": "function", 
"displayName": "Set Header", "group": "core", "label": "core", "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": 87, "kind": "function", 
"displayName": "Set Variable", "group": "core", "label": "core", "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": 88, "kind": "function", "displayName": 
"Shuffle Values", "group": "collection", "label": "collection", "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": 89, "kind": "function", "displayName": "Size", 
"group": "collection", "label": "collection", "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": 90, "kind": "function", "displayName": "Skip First 
Items from the Message Body", "group": "collection", "label": "collection", 
"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 [...]
-    "split(exp,separator)": { "index": 91, "kind": "function", "displayName": 
"Split String Values", "group": "collection", "label": "collection", 
"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": 92, "kind": "function", "displayName": "Step Id", 
"group": "core", "label": "core", "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": "}" },
-    "substring(head,tail)": { "index": 93, "kind": "function", "displayName": 
"Substring", "group": "string", "label": "string", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Returns a substring of 
the message body\/expression. If only one positive number, then the returned 
string is clipped from the beginning. If only one negative number, then the 
returned string is clipped from t [...]
-    "substringAfter(exp,before)": { "index": 94, "kind": "function", 
"displayName": "Substring After", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a substring of the message body\/expression that comes after. Returns 
null if nothing comes after.", "ognl": false, "suffix": "}" },
-    "substringBefore(exp,before)": { "index": 95, "kind": "function", 
"displayName": "Substring Before", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a substring of the message body\/expression that comes before. Returns 
null if nothing comes before.", "ognl": false, "suffix": "}" },
-    "substringBetween(exp,after,before)": { "index": 96, "kind": "function", 
"displayName": "Substring Between", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a substring of the message body\/expression that are between after and 
before. Returns null if nothing comes between.", "ognl": false, "suffix": "}" },
-    "sum(val...)": { "index": 97, "kind": "function", "displayName": 
"Calculate Sum Number", "group": "number", "label": "number", "required": 
false, "javaType": "long", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Sums together all the values as integral numbers. This function can also be 
used to subtract by using negative numbers.", "ognl": false, "suffix": "}" },
-    "sys.name": { "index": 98, "kind": "function", "displayName": "JVM System 
Property", "group": "other", "label": "other", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The JVM system property 
with the given name", "ognl": false, "suffix": "}" },
-    "threadId": { "index": 99, "kind": "function", "displayName": "Thread Id", 
"group": "other", "label": "other", "required": false, "javaType": "long", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Returns the id of the current thread. Can be 
used for logging.", "ognl": false, "suffix": "}" },
-    "threadName": { "index": 100, "kind": "function", "displayName": "Thread 
Name", "group": "other", "label": "other", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the name of the 
current thread. Can be used for logging.", "ognl": false, "suffix": "}" },
-    "throwException(type,msg)": { "index": 101, "kind": "function", 
"displayName": "Throw Exception", "group": "core", "label": "core", "required": 
false, "javaType": "java.lang.Exception", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Deliberately throws an error. Uses IllegalArgumentException by default if no 
type is specified (use fully qualified classname).", "ognl": false, "suffix": 
"}" },
-    "trim(exp)": { "index": 102, "kind": "function", "displayName": "Trim", 
"group": "string", "label": "string", "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": "}" },
-    "type:name.field": { "index": 103, "kind": "function", "displayName": 
"Java Field Value", "group": "core", "label": "core", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "To refer to a type or 
field by its classname. To refer to a field, you can append .FIELD_NAME. For 
example, you can refer to the constant field from Exchange as: 
`org.apache.camel.Exchange.FILE_NAME`", "ognl":  [...]
-    "kindOfType(exp)": { "index": 104, "kind": "function", "displayName": 
"Kind of Type", "group": "core", "label": "core", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "What kind of type is 
the value (null,number,string,boolean,array,object)", "ognl": false, "suffix": 
"}" },
-    "unquote(exp)": { "index": 105, "kind": "function", "displayName": 
"Unquote", "group": "string", "label": "string", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the message body 
(or expression) with any leading\/ending quotes removed", "ognl": false, 
"suffix": "}" },
-    "uppercase(exp)": { "index": 106, "kind": "function", "displayName": 
"Uppercase", "group": "string", "label": "string", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Uppercases the message 
body (or expression)", "ognl": false, "suffix": "}" },
-    "uuid(type)": { "index": 107, "kind": "function", "displayName": "Generate 
UUID", "group": "other", "label": "other", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns a UUID using the 
Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and 
`simple` as the type. If no type is given, the default is used. It is also 
possible to use a custom `UuidGenera [...]
-    "variable.name": { "index": 108, "kind": "function", "displayName": 
"Variable", "group": "core", "label": "core", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The variable with the 
given name", "ognl": true, "suffix": "}" },
-    "variableAs(key,type)": { "index": 109, "kind": "function", "displayName": 
"Variable As", "group": "core", "label": "core", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the variable to 
the given type (classname).", "ognl": false, "suffix": "}" },
-    "variables": { "index": 110, "kind": "function", "displayName": 
"Variables", "group": "core", "label": "core", "required": false, "javaType": 
"java.util.Map", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns all the variables 
from the current Exchange in a Map", "ognl": false, "suffix": "}" },
-    "xpath(input,exp)": { "index": 111, "kind": "function", "displayName": 
"XPath", "group": "xml", "label": "xml", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "When working with XML 
data, then this allows using the XPath language, for example, to extract data 
from the message body (in XML format). This requires having camel-xpath JAR on 
the classpath. For input (optional), you ca [...]
+    "range(min,max)": { "index": 79, "kind": "function", "displayName": 
"Range", "group": "number", "label": "number", "required": false, "javaType": 
"List", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns a list of 
increasing integers between the given interval (exclusive)", "ognl": false, 
"suffix": "}" },
+    "ref:name": { "index": 80, "kind": "function", "displayName": "Bean By 
Id", "group": "core", "label": "core", "required": false, "javaType": "Object", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "To look up a bean from the Registry with the 
given name.", "ognl": false, "suffix": "}" },
+    "replace(from,to,exp)": { "index": 81, "kind": "function", "displayName": 
"Replace String Values", "group": "string", "label": "string", "required": 
false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Replace all the string values in the message body\/expression. To make it 
easier to replace single and double quotes, then you can use XML escaped values 
`\\&quot;` as double quote, `\\&apos;` as s [...]
+    "reverse(val...)": { "index": 82, "kind": "function", "displayName": 
"Reverse Values", "group": "collection", "label": "collection", "required": 
false, "javaType": "List", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a list of all the values, but in reverse order", "ognl": false, 
"suffix": "}" },
+    "routeGroup": { "index": 83, "kind": "function", "displayName": "Route 
Group", "group": "core", "label": "core", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The route group of the 
current route the Exchange is being routed. Not all routes have a group 
assigned, so this may be null.", "ognl": false, "suffix": "}" },
+    "routeId": { "index": 84, "kind": "function", "displayName": "Route Id", 
"group": "core", "label": "core", "required": false, "javaType": "String", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The route id of the current route the Exchange 
is being routed", "ognl": false, "suffix": "}" },
+    "safeQuote(exp)": { "index": 85, "kind": "function", "displayName": "Safe 
Quote", "group": "string", "label": "string", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the message body 
(or expression) safely quoted if needed", "ognl": false, "suffix": "}" },
+    "setVariable(key,exp)": { "index": 86, "kind": "function", "displayName": 
"Set Variable", "group": "attachment", "label": "attachment", "required": 
false, "javaType": "Object", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Sets an attachment with payload from the message body\/expression.", "ognl": 
false, "suffix": "}" },
+    "setHeader(name,type,exp)": { "index": 87, "kind": "function", 
"displayName": "Set Header", "group": "core", "label": "core", "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": 88, "kind": "function", 
"displayName": "Set Variable", "group": "core", "label": "core", "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": 89, "kind": "function", "displayName": 
"Shuffle Values", "group": "collection", "label": "collection", "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": 90, "kind": "function", "displayName": "Size", 
"group": "collection", "label": "collection", "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": 91, "kind": "function", "displayName": "Skip First 
Items from the Message Body", "group": "collection", "label": "collection", 
"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 [...]
+    "split(exp,separator)": { "index": 92, "kind": "function", "displayName": 
"Split String Values", "group": "collection", "label": "collection", 
"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": 93, "kind": "function", "displayName": "Step Id", 
"group": "core", "label": "core", "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": "}" },
+    "substring(head,tail)": { "index": 94, "kind": "function", "displayName": 
"Substring", "group": "string", "label": "string", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Returns a substring of 
the message body\/expression. If only one positive number, then the returned 
string is clipped from the beginning. If only one negative number, then the 
returned string is clipped from t [...]
+    "substringAfter(exp,before)": { "index": 95, "kind": "function", 
"displayName": "Substring After", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a substring of the message body\/expression that comes after. Returns 
null if nothing comes after.", "ognl": false, "suffix": "}" },
+    "substringBefore(exp,before)": { "index": 96, "kind": "function", 
"displayName": "Substring Before", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a substring of the message body\/expression that comes before. Returns 
null if nothing comes before.", "ognl": false, "suffix": "}" },
+    "substringBetween(exp,after,before)": { "index": 97, "kind": "function", 
"displayName": "Substring Between", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a substring of the message body\/expression that are between after and 
before. Returns null if nothing comes between.", "ognl": false, "suffix": "}" },
+    "sum(val...)": { "index": 98, "kind": "function", "displayName": 
"Calculate Sum Number", "group": "number", "label": "number", "required": 
false, "javaType": "long", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Sums together all the values as integral numbers. This function can also be 
used to subtract by using negative numbers.", "ognl": false, "suffix": "}" },
+    "sys.name": { "index": 99, "kind": "function", "displayName": "JVM System 
Property", "group": "other", "label": "other", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The JVM system property 
with the given name", "ognl": false, "suffix": "}" },
+    "threadId": { "index": 100, "kind": "function", "displayName": "Thread 
Id", "group": "other", "label": "other", "required": false, "javaType": "long", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Returns the id of the current thread. Can be 
used for logging.", "ognl": false, "suffix": "}" },
+    "threadName": { "index": 101, "kind": "function", "displayName": "Thread 
Name", "group": "other", "label": "other", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the name of the 
current thread. Can be used for logging.", "ognl": false, "suffix": "}" },
+    "throwException(type,msg)": { "index": 102, "kind": "function", 
"displayName": "Throw Exception", "group": "core", "label": "core", "required": 
false, "javaType": "java.lang.Exception", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Deliberately throws an error. Uses IllegalArgumentException by default if no 
type is specified (use fully qualified classname).", "ognl": false, "suffix": 
"}" },
+    "trim(exp)": { "index": 103, "kind": "function", "displayName": "Trim", 
"group": "string", "label": "string", "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": "}" },
+    "type:name.field": { "index": 104, "kind": "function", "displayName": 
"Java Field Value", "group": "core", "label": "core", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "To refer to a type or 
field by its classname. To refer to a field, you can append .FIELD_NAME. For 
example, you can refer to the constant field from Exchange as: 
`org.apache.camel.Exchange.FILE_NAME`", "ognl":  [...]
+    "kindOfType(exp)": { "index": 105, "kind": "function", "displayName": 
"Kind of Type", "group": "core", "label": "core", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "What kind of type is 
the value (null,number,string,boolean,array,object)", "ognl": false, "suffix": 
"}" },
+    "unquote(exp)": { "index": 106, "kind": "function", "displayName": 
"Unquote", "group": "string", "label": "string", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the message body 
(or expression) with any leading\/ending quotes removed", "ognl": false, 
"suffix": "}" },
+    "uppercase(exp)": { "index": 107, "kind": "function", "displayName": 
"Uppercase", "group": "string", "label": "string", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Uppercases the message 
body (or expression)", "ognl": false, "suffix": "}" },
+    "uuid(type)": { "index": 108, "kind": "function", "displayName": "Generate 
UUID", "group": "other", "label": "other", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns a UUID using the 
Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and 
`simple` as the type. If no type is given, the default is used. It is also 
possible to use a custom `UuidGenera [...]
+    "variable.name": { "index": 109, "kind": "function", "displayName": 
"Variable", "group": "core", "label": "core", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The variable with the 
given name", "ognl": true, "suffix": "}" },
+    "variableAs(key,type)": { "index": 110, "kind": "function", "displayName": 
"Variable As", "group": "core", "label": "core", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the variable to 
the given type (classname).", "ognl": false, "suffix": "}" },
+    "variables": { "index": 111, "kind": "function", "displayName": 
"Variables", "group": "core", "label": "core", "required": false, "javaType": 
"java.util.Map", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns all the variables 
from the current Exchange in a Map", "ognl": false, "suffix": "}" },
+    "xpath(input,exp)": { "index": 112, "kind": "function", "displayName": 
"XPath", "group": "xml", "label": "xml", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "When working with XML 
data, then this allows using the XPath language, for example, to extract data 
from the message body (in XML format). This requires having camel-xpath JAR on 
the classpath. For input (optional), you ca [...]
   }
 }
diff --git 
a/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java
 
b/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java
index 09388acd2b14..2a77cd527523 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
@@ -2319,6 +2319,18 @@ public class OriginalSimpleTest extends 
LanguageTestSupport {
         assertEquals(f.length(), len);
     }
 
+    @Test
+    public void testRange() {
+        exchange.getMessage().setBody("5");
+        assertExpression("${range(1,4)}", "[1, 2, 3]");
+        assertExpression("${range(1,${body})}", "[1, 2, 3, 4]");
+        assertExpression("${range(0,10)}", "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
+        assertExpression("${range(1,2)}", "[1]");
+        assertExpression("${range(1,1)}", null);
+        assertExpression("${range(0,0)}", null);
+        assertExpression("${range(4,1)}", null);
+    }
+
     @Test
     public void testSubstringBefore() {
         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 49cbec39c26a..e1bc7744aff8 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
@@ -104,38 +104,39 @@
     "propertiesExist:key": { "index": 76, "kind": "function", "displayName": 
"Property Placeholder Exists", "group": "core", "label": "core", "required": 
false, "javaType": "boolean", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Checks whether a property placeholder with the given key exists or not. The 
result can be negated by prefixing the key with !", "ognl": false, "suffix": 
"}" },
     "quote(exp)": { "index": 77, "kind": "function", "displayName": "Quote", 
"group": "string", "label": "string", "required": false, "javaType": "String", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Returns the message body (or expression) as a 
double quoted string", "ognl": false, "suffix": "}" },
     "random(min,max)": { "index": 78, "kind": "function", "displayName": 
"Random", "group": "number", "label": "number", "required": false, "javaType": 
"int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Returns a random number between min and 
max (exclusive)", "ognl": false, "suffix": "}" },
-    "ref:name": { "index": 79, "kind": "function", "displayName": "Bean By 
Id", "group": "core", "label": "core", "required": false, "javaType": "Object", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "To look up a bean from the Registry with the 
given name.", "ognl": false, "suffix": "}" },
-    "replace(from,to,exp)": { "index": 80, "kind": "function", "displayName": 
"Replace String Values", "group": "string", "label": "string", "required": 
false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Replace all the string values in the message body\/expression. To make it 
easier to replace single and double quotes, then you can use XML escaped values 
`\\&quot;` as double quote, `\\&apos;` as s [...]
-    "reverse(val...)": { "index": 81, "kind": "function", "displayName": 
"Reverse Values", "group": "collection", "label": "collection", "required": 
false, "javaType": "List", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a list of all the values, but in reverse order", "ognl": false, 
"suffix": "}" },
-    "routeGroup": { "index": 82, "kind": "function", "displayName": "Route 
Group", "group": "core", "label": "core", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The route group of the 
current route the Exchange is being routed. Not all routes have a group 
assigned, so this may be null.", "ognl": false, "suffix": "}" },
-    "routeId": { "index": 83, "kind": "function", "displayName": "Route Id", 
"group": "core", "label": "core", "required": false, "javaType": "String", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The route id of the current route the Exchange 
is being routed", "ognl": false, "suffix": "}" },
-    "safeQuote(exp)": { "index": 84, "kind": "function", "displayName": "Safe 
Quote", "group": "string", "label": "string", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the message body 
(or expression) safely quoted if needed", "ognl": false, "suffix": "}" },
-    "setVariable(key,exp)": { "index": 85, "kind": "function", "displayName": 
"Set Variable", "group": "attachment", "label": "attachment", "required": 
false, "javaType": "Object", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Sets an attachment with payload from the message body\/expression.", "ognl": 
false, "suffix": "}" },
-    "setHeader(name,type,exp)": { "index": 86, "kind": "function", 
"displayName": "Set Header", "group": "core", "label": "core", "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": 87, "kind": "function", 
"displayName": "Set Variable", "group": "core", "label": "core", "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": 88, "kind": "function", "displayName": 
"Shuffle Values", "group": "collection", "label": "collection", "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": 89, "kind": "function", "displayName": "Size", 
"group": "collection", "label": "collection", "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": 90, "kind": "function", "displayName": "Skip First 
Items from the Message Body", "group": "collection", "label": "collection", 
"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 [...]
-    "split(exp,separator)": { "index": 91, "kind": "function", "displayName": 
"Split String Values", "group": "collection", "label": "collection", 
"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": 92, "kind": "function", "displayName": "Step Id", 
"group": "core", "label": "core", "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": "}" },
-    "substring(head,tail)": { "index": 93, "kind": "function", "displayName": 
"Substring", "group": "string", "label": "string", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Returns a substring of 
the message body\/expression. If only one positive number, then the returned 
string is clipped from the beginning. If only one negative number, then the 
returned string is clipped from t [...]
-    "substringAfter(exp,before)": { "index": 94, "kind": "function", 
"displayName": "Substring After", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a substring of the message body\/expression that comes after. Returns 
null if nothing comes after.", "ognl": false, "suffix": "}" },
-    "substringBefore(exp,before)": { "index": 95, "kind": "function", 
"displayName": "Substring Before", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a substring of the message body\/expression that comes before. Returns 
null if nothing comes before.", "ognl": false, "suffix": "}" },
-    "substringBetween(exp,after,before)": { "index": 96, "kind": "function", 
"displayName": "Substring Between", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a substring of the message body\/expression that are between after and 
before. Returns null if nothing comes between.", "ognl": false, "suffix": "}" },
-    "sum(val...)": { "index": 97, "kind": "function", "displayName": 
"Calculate Sum Number", "group": "number", "label": "number", "required": 
false, "javaType": "long", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Sums together all the values as integral numbers. This function can also be 
used to subtract by using negative numbers.", "ognl": false, "suffix": "}" },
-    "sys.name": { "index": 98, "kind": "function", "displayName": "JVM System 
Property", "group": "other", "label": "other", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The JVM system property 
with the given name", "ognl": false, "suffix": "}" },
-    "threadId": { "index": 99, "kind": "function", "displayName": "Thread Id", 
"group": "other", "label": "other", "required": false, "javaType": "long", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Returns the id of the current thread. Can be 
used for logging.", "ognl": false, "suffix": "}" },
-    "threadName": { "index": 100, "kind": "function", "displayName": "Thread 
Name", "group": "other", "label": "other", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the name of the 
current thread. Can be used for logging.", "ognl": false, "suffix": "}" },
-    "throwException(type,msg)": { "index": 101, "kind": "function", 
"displayName": "Throw Exception", "group": "core", "label": "core", "required": 
false, "javaType": "java.lang.Exception", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Deliberately throws an error. Uses IllegalArgumentException by default if no 
type is specified (use fully qualified classname).", "ognl": false, "suffix": 
"}" },
-    "trim(exp)": { "index": 102, "kind": "function", "displayName": "Trim", 
"group": "string", "label": "string", "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": "}" },
-    "type:name.field": { "index": 103, "kind": "function", "displayName": 
"Java Field Value", "group": "core", "label": "core", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "To refer to a type or 
field by its classname. To refer to a field, you can append .FIELD_NAME. For 
example, you can refer to the constant field from Exchange as: 
`org.apache.camel.Exchange.FILE_NAME`", "ognl":  [...]
-    "kindOfType(exp)": { "index": 104, "kind": "function", "displayName": 
"Kind of Type", "group": "core", "label": "core", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "What kind of type is 
the value (null,number,string,boolean,array,object)", "ognl": false, "suffix": 
"}" },
-    "unquote(exp)": { "index": 105, "kind": "function", "displayName": 
"Unquote", "group": "string", "label": "string", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the message body 
(or expression) with any leading\/ending quotes removed", "ognl": false, 
"suffix": "}" },
-    "uppercase(exp)": { "index": 106, "kind": "function", "displayName": 
"Uppercase", "group": "string", "label": "string", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Uppercases the message 
body (or expression)", "ognl": false, "suffix": "}" },
-    "uuid(type)": { "index": 107, "kind": "function", "displayName": "Generate 
UUID", "group": "other", "label": "other", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns a UUID using the 
Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and 
`simple` as the type. If no type is given, the default is used. It is also 
possible to use a custom `UuidGenera [...]
-    "variable.name": { "index": 108, "kind": "function", "displayName": 
"Variable", "group": "core", "label": "core", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The variable with the 
given name", "ognl": true, "suffix": "}" },
-    "variableAs(key,type)": { "index": 109, "kind": "function", "displayName": 
"Variable As", "group": "core", "label": "core", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the variable to 
the given type (classname).", "ognl": false, "suffix": "}" },
-    "variables": { "index": 110, "kind": "function", "displayName": 
"Variables", "group": "core", "label": "core", "required": false, "javaType": 
"java.util.Map", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns all the variables 
from the current Exchange in a Map", "ognl": false, "suffix": "}" },
-    "xpath(input,exp)": { "index": 111, "kind": "function", "displayName": 
"XPath", "group": "xml", "label": "xml", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "When working with XML 
data, then this allows using the XPath language, for example, to extract data 
from the message body (in XML format). This requires having camel-xpath JAR on 
the classpath. For input (optional), you ca [...]
+    "range(min,max)": { "index": 79, "kind": "function", "displayName": 
"Range", "group": "number", "label": "number", "required": false, "javaType": 
"List", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns a list of 
increasing integers between the given interval (exclusive)", "ognl": false, 
"suffix": "}" },
+    "ref:name": { "index": 80, "kind": "function", "displayName": "Bean By 
Id", "group": "core", "label": "core", "required": false, "javaType": "Object", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "To look up a bean from the Registry with the 
given name.", "ognl": false, "suffix": "}" },
+    "replace(from,to,exp)": { "index": 81, "kind": "function", "displayName": 
"Replace String Values", "group": "string", "label": "string", "required": 
false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Replace all the string values in the message body\/expression. To make it 
easier to replace single and double quotes, then you can use XML escaped values 
`\\&quot;` as double quote, `\\&apos;` as s [...]
+    "reverse(val...)": { "index": 82, "kind": "function", "displayName": 
"Reverse Values", "group": "collection", "label": "collection", "required": 
false, "javaType": "List", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a list of all the values, but in reverse order", "ognl": false, 
"suffix": "}" },
+    "routeGroup": { "index": 83, "kind": "function", "displayName": "Route 
Group", "group": "core", "label": "core", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The route group of the 
current route the Exchange is being routed. Not all routes have a group 
assigned, so this may be null.", "ognl": false, "suffix": "}" },
+    "routeId": { "index": 84, "kind": "function", "displayName": "Route Id", 
"group": "core", "label": "core", "required": false, "javaType": "String", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The route id of the current route the Exchange 
is being routed", "ognl": false, "suffix": "}" },
+    "safeQuote(exp)": { "index": 85, "kind": "function", "displayName": "Safe 
Quote", "group": "string", "label": "string", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the message body 
(or expression) safely quoted if needed", "ognl": false, "suffix": "}" },
+    "setVariable(key,exp)": { "index": 86, "kind": "function", "displayName": 
"Set Variable", "group": "attachment", "label": "attachment", "required": 
false, "javaType": "Object", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Sets an attachment with payload from the message body\/expression.", "ognl": 
false, "suffix": "}" },
+    "setHeader(name,type,exp)": { "index": 87, "kind": "function", 
"displayName": "Set Header", "group": "core", "label": "core", "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": 88, "kind": "function", 
"displayName": "Set Variable", "group": "core", "label": "core", "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": 89, "kind": "function", "displayName": 
"Shuffle Values", "group": "collection", "label": "collection", "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": 90, "kind": "function", "displayName": "Size", 
"group": "collection", "label": "collection", "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": 91, "kind": "function", "displayName": "Skip First 
Items from the Message Body", "group": "collection", "label": "collection", 
"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 [...]
+    "split(exp,separator)": { "index": 92, "kind": "function", "displayName": 
"Split String Values", "group": "collection", "label": "collection", 
"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": 93, "kind": "function", "displayName": "Step Id", 
"group": "core", "label": "core", "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": "}" },
+    "substring(head,tail)": { "index": 94, "kind": "function", "displayName": 
"Substring", "group": "string", "label": "string", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Returns a substring of 
the message body\/expression. If only one positive number, then the returned 
string is clipped from the beginning. If only one negative number, then the 
returned string is clipped from t [...]
+    "substringAfter(exp,before)": { "index": 95, "kind": "function", 
"displayName": "Substring After", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a substring of the message body\/expression that comes after. Returns 
null if nothing comes after.", "ognl": false, "suffix": "}" },
+    "substringBefore(exp,before)": { "index": 96, "kind": "function", 
"displayName": "Substring Before", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a substring of the message body\/expression that comes before. Returns 
null if nothing comes before.", "ognl": false, "suffix": "}" },
+    "substringBetween(exp,after,before)": { "index": 97, "kind": "function", 
"displayName": "Substring Between", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns a substring of the message body\/expression that are between after and 
before. Returns null if nothing comes between.", "ognl": false, "suffix": "}" },
+    "sum(val...)": { "index": 98, "kind": "function", "displayName": 
"Calculate Sum Number", "group": "number", "label": "number", "required": 
false, "javaType": "long", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Sums together all the values as integral numbers. This function can also be 
used to subtract by using negative numbers.", "ognl": false, "suffix": "}" },
+    "sys.name": { "index": 99, "kind": "function", "displayName": "JVM System 
Property", "group": "other", "label": "other", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The JVM system property 
with the given name", "ognl": false, "suffix": "}" },
+    "threadId": { "index": 100, "kind": "function", "displayName": "Thread 
Id", "group": "other", "label": "other", "required": false, "javaType": "long", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Returns the id of the current thread. Can be 
used for logging.", "ognl": false, "suffix": "}" },
+    "threadName": { "index": 101, "kind": "function", "displayName": "Thread 
Name", "group": "other", "label": "other", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the name of the 
current thread. Can be used for logging.", "ognl": false, "suffix": "}" },
+    "throwException(type,msg)": { "index": 102, "kind": "function", 
"displayName": "Throw Exception", "group": "core", "label": "core", "required": 
false, "javaType": "java.lang.Exception", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Deliberately throws an error. Uses IllegalArgumentException by default if no 
type is specified (use fully qualified classname).", "ognl": false, "suffix": 
"}" },
+    "trim(exp)": { "index": 103, "kind": "function", "displayName": "Trim", 
"group": "string", "label": "string", "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": "}" },
+    "type:name.field": { "index": 104, "kind": "function", "displayName": 
"Java Field Value", "group": "core", "label": "core", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "To refer to a type or 
field by its classname. To refer to a field, you can append .FIELD_NAME. For 
example, you can refer to the constant field from Exchange as: 
`org.apache.camel.Exchange.FILE_NAME`", "ognl":  [...]
+    "kindOfType(exp)": { "index": 105, "kind": "function", "displayName": 
"Kind of Type", "group": "core", "label": "core", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "What kind of type is 
the value (null,number,string,boolean,array,object)", "ognl": false, "suffix": 
"}" },
+    "unquote(exp)": { "index": 106, "kind": "function", "displayName": 
"Unquote", "group": "string", "label": "string", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the message body 
(or expression) with any leading\/ending quotes removed", "ognl": false, 
"suffix": "}" },
+    "uppercase(exp)": { "index": 107, "kind": "function", "displayName": 
"Uppercase", "group": "string", "label": "string", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Uppercases the message 
body (or expression)", "ognl": false, "suffix": "}" },
+    "uuid(type)": { "index": 108, "kind": "function", "displayName": "Generate 
UUID", "group": "other", "label": "other", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns a UUID using the 
Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and 
`simple` as the type. If no type is given, the default is used. It is also 
possible to use a custom `UuidGenera [...]
+    "variable.name": { "index": 109, "kind": "function", "displayName": 
"Variable", "group": "core", "label": "core", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The variable with the 
given name", "ognl": true, "suffix": "}" },
+    "variableAs(key,type)": { "index": 110, "kind": "function", "displayName": 
"Variable As", "group": "core", "label": "core", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the variable to 
the given type (classname).", "ognl": false, "suffix": "}" },
+    "variables": { "index": 111, "kind": "function", "displayName": 
"Variables", "group": "core", "label": "core", "required": false, "javaType": 
"java.util.Map", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns all the variables 
from the current Exchange in a Map", "ognl": false, "suffix": "}" },
+    "xpath(input,exp)": { "index": 112, "kind": "function", "displayName": 
"XPath", "group": "xml", "label": "xml", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "When working with XML 
data, then this allows using the XPath language, for example, to extract data 
from the message body (in XML format). This requires having camel-xpath JAR on 
the classpath. For input (optional), you ca [...]
   }
 }
diff --git 
a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
 
b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
index c21550d979da..d04120b822dc 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
@@ -387,7 +387,9 @@ Various functions to work with numbers.
 |`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),
+|`random(min,max)` | `int` | Returns a random `Integer` between min (included) 
and max (excluded).
+|`range(max)` | `List` | Returns a list of increasing integers between 0 
(included) and max (excluded).
+|`range(min,max)` | `List` | Returns a list of increasing integers between min 
(included) and max (excluded).
 |`sum(val1,val2,...)` | `long` | Sums together all the values as integral 
numbers. This function can also be used to subtract by using negative numbers.
 |====
 
@@ -409,6 +411,9 @@ For example message body contains a list `[10, 5, 30, 15]` 
then `${max()}` retur
 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 `range` functions returns a list of increasing numbers between min and max 
(exclusive).
+For example `${range(10)}` returns the numbers `0..9`. And `${range(1,10)}` 
returns `1..9`.
+
 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
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 543d070af435..810c998e5f4d 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
@@ -713,6 +713,19 @@ public final class CSimpleHelper {
         return random.nextInt(num2 - num1) + num1;
     }
 
+    public static List<Integer> rangeList(Exchange exchange, Object min, 
Object max) {
+        int num1 = 
exchange.getContext().getTypeConverter().tryConvertTo(int.class, exchange, min);
+        int num2 = 
exchange.getContext().getTypeConverter().tryConvertTo(int.class, exchange, max);
+        if (num1 >= 0 && num1 <= num2 && num1 != num2) {
+            List<Integer> answer = new ArrayList<>();
+            for (int i = num1; i < num2; i++) {
+                answer.add(i);
+            }
+            return answer;
+        }
+        return null;
+    }
+
     public static SkipIterator skip(Exchange exchange, Object skip) {
         int num = 
exchange.getContext().getTypeConverter().tryConvertTo(int.class, exchange, 
skip);
         Iterator<?> it = 
org.apache.camel.support.ObjectHelper.createIterator(exchange.getMessage().getBody());
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 e6575287f7a1..d7358cb22863 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
@@ -322,6 +322,10 @@ public final class SimpleConstants {
               label = "number", javaType = "int")
     public static final String RANDOM = "random(min,max)";
 
+    @Metadata(description = "Returns a list of increasing integers between the 
given interval (exclusive)",
+              label = "number", javaType = "List")
+    public static final String RANGE = "range(min,max)";
+
     @Metadata(description = "To look up a bean from the Registry with the 
given name.", label = "core", javaType = "Object",
               displayName = "Bean By Id")
     public static final String REF = "ref:name";
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 9fd33f562017..aaaba55c76f9 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
@@ -2193,6 +2193,43 @@ public final class SimpleExpressionBuilder {
         };
     }
 
+    /**
+     * Returns a range of number between min and max (exclusive)
+     */
+    public static Expression rangeExpression(final String min, final String 
max) {
+        return new ExpressionAdapter() {
+            private Expression exp1;
+            private Expression exp2;
+
+            @Override
+            public Object evaluate(Exchange exchange) {
+                int num1 = exp1.evaluate(exchange, Integer.class);
+                int num2 = exp2.evaluate(exchange, Integer.class);
+                if (num1 >= 0 && num1 <= num2 && num1 != num2) {
+                    List<Integer> answer = new ArrayList<>();
+                    for (int i = num1; i < num2; i++) {
+                        answer.add(i);
+                    }
+                    return answer;
+                }
+                return null;
+            }
+
+            @Override
+            public void init(CamelContext context) {
+                exp1 = ExpressionBuilder.simpleExpression(min);
+                exp1.init(context);
+                exp2 = ExpressionBuilder.simpleExpression(max);
+                exp2.init(context);
+            }
+
+            @Override
+            public String toString() {
+                return "range(" + min + "," + max + ")";
+            }
+        };
+    }
+
     /**
      * Returns a random number between 0 and max (exclusive)
      */
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 c5333495c46f..1e8aa3394409 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
@@ -1021,6 +1021,25 @@ public class SimpleFunctionExpression extends 
LiteralExpression {
                 return SimpleExpressionBuilder.randomExpression("0", 
values.trim());
             }
         }
+        // range function
+        remainder = ifStartsWithReturnRemainder("range(", function);
+        if (remainder != null) {
+            String values = StringHelper.beforeLast(remainder, ")");
+            if (values == null || ObjectHelper.isEmpty(values)) {
+                throw new SimpleParserException(
+                        "Valid syntax: ${range(min,max)} or ${range(max)} was: 
" + function, token.getIndex());
+            }
+            if (values.contains(",")) {
+                String[] tokens = values.split(",", 3);
+                if (tokens.length > 2) {
+                    throw new SimpleParserException(
+                            "Valid syntax: ${range(min,max)} or ${range(max)} 
was: " + function, token.getIndex());
+                }
+                return 
SimpleExpressionBuilder.rangeExpression(tokens[0].trim(), tokens[1].trim());
+            } else {
+                return SimpleExpressionBuilder.rangeExpression("1", 
values.trim());
+            }
+        }
 
         // distinct function
         remainder = ifStartsWithReturnRemainder("distinct(", function);
@@ -2834,6 +2853,26 @@ public class SimpleFunctionExpression extends 
LiteralExpression {
                 return "random(exchange, 0, " + values.trim() + ")";
             }
         }
+        remainder = ifStartsWithReturnRemainder("range(", function);
+        if (remainder != null) {
+            String values = StringHelper.beforeLast(remainder, ")");
+            if (values == null || ObjectHelper.isEmpty(values)) {
+                throw new SimpleParserException(
+                        "Valid syntax: ${range(min,max)} or ${range(max)} was: 
" + function, token.getIndex());
+            }
+            if (values.contains(",")) {
+                String before = StringHelper.before(remainder, ",");
+                before = before.trim();
+                String after = StringHelper.after(remainder, ",");
+                after = after.trim();
+                if (after.endsWith(")")) {
+                    after = after.substring(0, after.length() - 1);
+                }
+                return "rangeList(exchange, " + before + ", " + after + ")";
+            } else {
+                return "rangeList(exchange, 0, " + values.trim() + ")";
+            }
+        }
 
         // replace function
         remainder = ifStartsWithReturnRemainder("replace(", function);
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 fb14c247b4ab..18a6e837cd8a 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
@@ -2158,6 +2158,18 @@ public class SimpleTest extends LanguageTestSupport {
         assertExpression("${map()}", "{}");
     }
 
+    @Test
+    public void testRange() {
+        exchange.getMessage().setBody("5");
+        assertExpression("${range(1,4)}", "[1, 2, 3]");
+        assertExpression("${range(1,${body})}", "[1, 2, 3, 4]");
+        assertExpression("${range(0,10)}", "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
+        assertExpression("${range(1,2)}", "[1]");
+        assertExpression("${range(1,1)}", null);
+        assertExpression("${range(0,0)}", null);
+        assertExpression("${range(4,1)}", null);
+    }
+
     @Test
     public void testSubstringExpression() {
         exchange.getMessage().setBody("ABCDEFGHIJK");
diff --git 
a/core/camel-util/src/main/java/org/apache/camel/util/SimpleUtils.java 
b/core/camel-util/src/main/java/org/apache/camel/util/SimpleUtils.java
index b55cba73b9d4..a94fef3d9b55 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/SimpleUtils.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/SimpleUtils.java
@@ -105,6 +105,7 @@ public class SimpleUtils {
                     "propertiesexist",
                     "quote",
                     "random",
+                    "range",
                     "ref",
                     "replace",
                     "reverse",

Reply via email to