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 cf923a32b220 CAMEL-23053: camel-core - Add mapAdd/mapRemove functions 
to simple la… (#21874)
cf923a32b220 is described below

commit cf923a32b220d577b6692cebea84e9eb1a427dbb
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Mar 9 15:51:50 2026 +0100

    CAMEL-23053: camel-core - Add mapAdd/mapRemove functions to simple la… 
(#21874)
    
    * CAMEL-23053: camel-core - Add mapAdd/mapRemove functions to simple 
language
---
 .../org/apache/camel/catalog/languages/simple.json | 116 +++++++++++----------
 .../org/apache/camel/language/simple/simple.json   | 116 +++++++++++----------
 .../modules/languages/pages/simple-language.adoc   |  15 ++-
 .../camel/language/simple/SimpleConstants.java     |   8 ++
 .../language/simple/SimpleExpressionBuilder.java   |  68 ++++++++++++
 .../simple/ast/SimpleFunctionExpression.java       |  50 +++++++++
 .../apache/camel/language/simple/SimpleTest.java   |  59 +++++++++++
 .../java/org/apache/camel/util/SimpleUtils.java    |   2 +
 8 files changed, 318 insertions(+), 116 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 c2d8b8ef7f07..9719e79478a4 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
@@ -91,62 +91,64 @@
     "lowercase(exp)": { "index": 63, "kind": "function", "displayName": 
"Lowercase", "group": "string", "label": "string", "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": 64, "kind": "function", "displayName": 
"Mandatory Body As", "group": "core", "label": "core", "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": 65, "kind": "function", "displayName": 
"Create Map of pairs", "group": "collection", "label": "collection", 
"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": 66, "kind": "function", "displayName": "Maximum 
Number", "group": "number", "label": "number", "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": 67, "kind": "function", "displayName": 
"Message As", "group": "core", "label": "core", "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": 68, "kind": "function", 
"displayName": "Print Message History", "group": "core", "label": "core", 
"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 boolean c [...]
-    "messageTimestamp": { "index": 69, "kind": "function", "displayName": 
"Message Timestamp", "group": "core", "label": "core", "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 timestamp if a t [...]
-    "min(val...)": { "index": 70, "kind": "function", "displayName": "Minimum 
Number", "group": "number", "label": "number", "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": 71, "kind": "function", "displayName": 
"Create Empty Object", "group": "collection", "label": "collection", 
"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`. Us [...]
-    "normalizeWhitespace(exp)": { "index": 72, "kind": "function", 
"displayName": "Normalize Whitespace", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Normalizes the whitespace in the message body (or expression) by cleaning up 
excess whitespaces.", "ognl": false, "suffix": "}" },
-    "not": { "index": 73, "kind": "function", "displayName": "Not", "group": 
"condition", "label": "condition", "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": 74, "kind": "function", "displayName": "Null", "group": 
"other", "label": "other", "required": false, "javaType": "Object", "prefix": 
"${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Returns a null value", "ognl": false, "suffix": "}" },
-    "originalBody": { "index": 75, "kind": "function", "displayName": 
"Original Body", "group": "core", "label": "core", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "The original incoming 
body (only available if allowUseOriginalMessage=true).", "ognl": false, 
"suffix": "}" },
-    "pad(exp,width,separator)": { "index": 76, "kind": "function", 
"displayName": "Pad String", "group": "string", "label": "string", "required": 
false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Pads the expression with extra padding if necessary, according the the total 
width. The separator is by default a space. If the width is negative then 
padding to the right, otherwise to the left.", "ognl" [...]
-    "pretty(exp)": { "index": 77, "kind": "function", "displayName": "Pretty 
Print", "group": "xml", "label": "json,xml", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the expression to 
a String, and attempts to pretty print if JSon or XML, otherwise the expression 
is returned as the String value.", "ognl": false, "suffix": "}" },
-    "prettyBody": { "index": 78, "kind": "function", "displayName": "Pretty 
Body", "group": "xml", "label": "json,xml", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the body to a 
String, and attempts to pretty print if JSon or XML; otherwise the body is 
returned as the String value.", "ognl": false, "suffix": "}" },
-    "sort(exp,reverse)": { "index": 79, "kind": "function", "displayName": 
"Sort", "group": "collection", "label": "collection", "required": false, 
"javaType": "List", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Sorts the message body or 
expression in natural order", "ognl": false, "suffix": "}" },
-    "toPrettyJson(exp)": { "index": 80, "kind": "function", "displayName": "To 
Pretty JSon", "group": "json", "label": "json", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the expression to 
JSon String representation.", "ognl": false, "suffix": "}" },
-    "toPrettyJsonBody": { "index": 81, "kind": "function", "displayName": "To 
Pretty JSon Body", "group": "json", "label": "json", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Converts the body to 
JSon String representation.", "ognl": false, "suffix": "}" },
-    "toJson(exp)": { "index": 82, "kind": "function", "displayName": "To 
JSon", "group": "json", "label": "json", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the expression to 
JSon String representation.", "ognl": false, "suffix": "}" },
-    "toJsonBody": { "index": 83, "kind": "function", "displayName": "To JSon 
Body", "group": "json", "label": "json", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the body to JSon 
String representation.", "ognl": false, "suffix": "}" },
-    "properties:key:default": { "index": 84, "kind": "function", 
"displayName": "Property Placeholder", "group": "core", "label": "core", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Lookup a property placeholder with the given key. If the key does not exist 
nor has a value, then an optional default value can be specified.", "ognl": 
false, "suffix": "}" },
-    "propertiesExist:key": { "index": 85, "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": 86, "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": 87, "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": "}" },
-    "range(min,max)": { "index": 88, "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": 89, "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": 90, "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": 91, "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": 92, "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": 93, "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": 94, "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": 95, "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": 96, "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": 97, "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": 98, "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": 99, "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": 100, "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 numbe [...]
-    "split(exp,separator)": { "index": 101, "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": 102, "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": 103, "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  [...]
-    "substringAfter(exp,before)": { "index": 104, "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": 105, "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": 106, "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": 107, "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": 108, "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": 109, "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": 110, "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": 111, "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": 112, "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": 113, "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": 114, "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": 115, "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": 116, "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": 117, "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 [...]
-    "val(exp)": { "index": 118, "kind": "function", "displayName": "Value", 
"group": "core", "label": "core", "required": false, "javaType": "Object", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Returns the expression as a constant value", 
"ognl": false, "suffix": "}" },
-    "variable.name": { "index": 119, "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": 120, "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": 121, "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": 122, "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 [...]
+    "mapAdd(source,key,exp)": { "index": 66, "kind": "function", 
"displayName": "Map Add", "group": "collection", "label": "collection", 
"required": false, "javaType": "Map", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Adds the result of the expression to the message body (or expression) which is 
a map", "ognl": false, "suffix": "}" },
+    "mapRemove(source,key)": { "index": 67, "kind": "function", "displayName": 
"Map Remove", "group": "collection", "label": "collection", "required": false, 
"javaType": "Map", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Removes the result of the 
expression from the message body (or expression) which is a map", "ognl": 
false, "suffix": "}" },
+    "max(val...)": { "index": 68, "kind": "function", "displayName": "Maximum 
Number", "group": "number", "label": "number", "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": 69, "kind": "function", "displayName": 
"Message As", "group": "core", "label": "core", "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": 70, "kind": "function", 
"displayName": "Print Message History", "group": "core", "label": "core", 
"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 boolean c [...]
+    "messageTimestamp": { "index": 71, "kind": "function", "displayName": 
"Message Timestamp", "group": "core", "label": "core", "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 timestamp if a t [...]
+    "min(val...)": { "index": 72, "kind": "function", "displayName": "Minimum 
Number", "group": "number", "label": "number", "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": 73, "kind": "function", "displayName": 
"Create Empty Object", "group": "collection", "label": "collection", 
"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`. Us [...]
+    "normalizeWhitespace(exp)": { "index": 74, "kind": "function", 
"displayName": "Normalize Whitespace", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Normalizes the whitespace in the message body (or expression) by cleaning up 
excess whitespaces.", "ognl": false, "suffix": "}" },
+    "not": { "index": 75, "kind": "function", "displayName": "Not", "group": 
"condition", "label": "condition", "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": 76, "kind": "function", "displayName": "Null", "group": 
"other", "label": "other", "required": false, "javaType": "Object", "prefix": 
"${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Returns a null value", "ognl": false, "suffix": "}" },
+    "originalBody": { "index": 77, "kind": "function", "displayName": 
"Original Body", "group": "core", "label": "core", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "The original incoming 
body (only available if allowUseOriginalMessage=true).", "ognl": false, 
"suffix": "}" },
+    "pad(exp,width,separator)": { "index": 78, "kind": "function", 
"displayName": "Pad String", "group": "string", "label": "string", "required": 
false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Pads the expression with extra padding if necessary, according the the total 
width. The separator is by default a space. If the width is negative then 
padding to the right, otherwise to the left.", "ognl" [...]
+    "pretty(exp)": { "index": 79, "kind": "function", "displayName": "Pretty 
Print", "group": "xml", "label": "json,xml", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the expression to 
a String, and attempts to pretty print if JSon or XML, otherwise the expression 
is returned as the String value.", "ognl": false, "suffix": "}" },
+    "prettyBody": { "index": 80, "kind": "function", "displayName": "Pretty 
Body", "group": "xml", "label": "json,xml", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the body to a 
String, and attempts to pretty print if JSon or XML; otherwise the body is 
returned as the String value.", "ognl": false, "suffix": "}" },
+    "sort(exp,reverse)": { "index": 81, "kind": "function", "displayName": 
"Sort", "group": "collection", "label": "collection", "required": false, 
"javaType": "List", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Sorts the message body or 
expression in natural order", "ognl": false, "suffix": "}" },
+    "toPrettyJson(exp)": { "index": 82, "kind": "function", "displayName": "To 
Pretty JSon", "group": "json", "label": "json", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the expression to 
JSon String representation.", "ognl": false, "suffix": "}" },
+    "toPrettyJsonBody": { "index": 83, "kind": "function", "displayName": "To 
Pretty JSon Body", "group": "json", "label": "json", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Converts the body to 
JSon String representation.", "ognl": false, "suffix": "}" },
+    "toJson(exp)": { "index": 84, "kind": "function", "displayName": "To 
JSon", "group": "json", "label": "json", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the expression to 
JSon String representation.", "ognl": false, "suffix": "}" },
+    "toJsonBody": { "index": 85, "kind": "function", "displayName": "To JSon 
Body", "group": "json", "label": "json", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the body to JSon 
String representation.", "ognl": false, "suffix": "}" },
+    "properties:key:default": { "index": 86, "kind": "function", 
"displayName": "Property Placeholder", "group": "core", "label": "core", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Lookup a property placeholder with the given key. If the key does not exist 
nor has a value, then an optional default value can be specified.", "ognl": 
false, "suffix": "}" },
+    "propertiesExist:key": { "index": 87, "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": 88, "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": 89, "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": "}" },
+    "range(min,max)": { "index": 90, "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": 91, "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": 92, "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": 93, "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": 94, "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": 95, "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": 96, "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": 97, "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": 98, "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": 99, "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": 100, "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": 101, "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": 102, "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 numbe [...]
+    "split(exp,separator)": { "index": 103, "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": 104, "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": 105, "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  [...]
+    "substringAfter(exp,before)": { "index": 106, "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": 107, "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": 108, "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": 109, "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": 110, "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": 111, "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": 112, "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": 113, "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": 114, "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": 115, "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": 116, "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": 117, "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": 118, "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": 119, "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 [...]
+    "val(exp)": { "index": 120, "kind": "function", "displayName": "Value", 
"group": "core", "label": "core", "required": false, "javaType": "Object", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Returns the expression as a constant value", 
"ognl": false, "suffix": "}" },
+    "variable.name": { "index": 121, "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": 122, "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": 123, "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": 124, "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/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 c2d8b8ef7f07..9719e79478a4 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
@@ -91,62 +91,64 @@
     "lowercase(exp)": { "index": 63, "kind": "function", "displayName": 
"Lowercase", "group": "string", "label": "string", "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": 64, "kind": "function", "displayName": 
"Mandatory Body As", "group": "core", "label": "core", "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": 65, "kind": "function", "displayName": 
"Create Map of pairs", "group": "collection", "label": "collection", 
"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": 66, "kind": "function", "displayName": "Maximum 
Number", "group": "number", "label": "number", "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": 67, "kind": "function", "displayName": 
"Message As", "group": "core", "label": "core", "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": 68, "kind": "function", 
"displayName": "Print Message History", "group": "core", "label": "core", 
"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 boolean c [...]
-    "messageTimestamp": { "index": 69, "kind": "function", "displayName": 
"Message Timestamp", "group": "core", "label": "core", "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 timestamp if a t [...]
-    "min(val...)": { "index": 70, "kind": "function", "displayName": "Minimum 
Number", "group": "number", "label": "number", "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": 71, "kind": "function", "displayName": 
"Create Empty Object", "group": "collection", "label": "collection", 
"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`. Us [...]
-    "normalizeWhitespace(exp)": { "index": 72, "kind": "function", 
"displayName": "Normalize Whitespace", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Normalizes the whitespace in the message body (or expression) by cleaning up 
excess whitespaces.", "ognl": false, "suffix": "}" },
-    "not": { "index": 73, "kind": "function", "displayName": "Not", "group": 
"condition", "label": "condition", "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": 74, "kind": "function", "displayName": "Null", "group": 
"other", "label": "other", "required": false, "javaType": "Object", "prefix": 
"${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Returns a null value", "ognl": false, "suffix": "}" },
-    "originalBody": { "index": 75, "kind": "function", "displayName": 
"Original Body", "group": "core", "label": "core", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "The original incoming 
body (only available if allowUseOriginalMessage=true).", "ognl": false, 
"suffix": "}" },
-    "pad(exp,width,separator)": { "index": 76, "kind": "function", 
"displayName": "Pad String", "group": "string", "label": "string", "required": 
false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Pads the expression with extra padding if necessary, according the the total 
width. The separator is by default a space. If the width is negative then 
padding to the right, otherwise to the left.", "ognl" [...]
-    "pretty(exp)": { "index": 77, "kind": "function", "displayName": "Pretty 
Print", "group": "xml", "label": "json,xml", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the expression to 
a String, and attempts to pretty print if JSon or XML, otherwise the expression 
is returned as the String value.", "ognl": false, "suffix": "}" },
-    "prettyBody": { "index": 78, "kind": "function", "displayName": "Pretty 
Body", "group": "xml", "label": "json,xml", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the body to a 
String, and attempts to pretty print if JSon or XML; otherwise the body is 
returned as the String value.", "ognl": false, "suffix": "}" },
-    "sort(exp,reverse)": { "index": 79, "kind": "function", "displayName": 
"Sort", "group": "collection", "label": "collection", "required": false, 
"javaType": "List", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Sorts the message body or 
expression in natural order", "ognl": false, "suffix": "}" },
-    "toPrettyJson(exp)": { "index": 80, "kind": "function", "displayName": "To 
Pretty JSon", "group": "json", "label": "json", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the expression to 
JSon String representation.", "ognl": false, "suffix": "}" },
-    "toPrettyJsonBody": { "index": 81, "kind": "function", "displayName": "To 
Pretty JSon Body", "group": "json", "label": "json", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Converts the body to 
JSon String representation.", "ognl": false, "suffix": "}" },
-    "toJson(exp)": { "index": 82, "kind": "function", "displayName": "To 
JSon", "group": "json", "label": "json", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the expression to 
JSon String representation.", "ognl": false, "suffix": "}" },
-    "toJsonBody": { "index": 83, "kind": "function", "displayName": "To JSon 
Body", "group": "json", "label": "json", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the body to JSon 
String representation.", "ognl": false, "suffix": "}" },
-    "properties:key:default": { "index": 84, "kind": "function", 
"displayName": "Property Placeholder", "group": "core", "label": "core", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Lookup a property placeholder with the given key. If the key does not exist 
nor has a value, then an optional default value can be specified.", "ognl": 
false, "suffix": "}" },
-    "propertiesExist:key": { "index": 85, "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": 86, "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": 87, "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": "}" },
-    "range(min,max)": { "index": 88, "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": 89, "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": 90, "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": 91, "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": 92, "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": 93, "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": 94, "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": 95, "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": 96, "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": 97, "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": 98, "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": 99, "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": 100, "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 numbe [...]
-    "split(exp,separator)": { "index": 101, "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": 102, "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": 103, "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  [...]
-    "substringAfter(exp,before)": { "index": 104, "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": 105, "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": 106, "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": 107, "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": 108, "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": 109, "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": 110, "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": 111, "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": 112, "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": 113, "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": 114, "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": 115, "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": 116, "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": 117, "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 [...]
-    "val(exp)": { "index": 118, "kind": "function", "displayName": "Value", 
"group": "core", "label": "core", "required": false, "javaType": "Object", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Returns the expression as a constant value", 
"ognl": false, "suffix": "}" },
-    "variable.name": { "index": 119, "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": 120, "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": 121, "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": 122, "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 [...]
+    "mapAdd(source,key,exp)": { "index": 66, "kind": "function", 
"displayName": "Map Add", "group": "collection", "label": "collection", 
"required": false, "javaType": "Map", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Adds the result of the expression to the message body (or expression) which is 
a map", "ognl": false, "suffix": "}" },
+    "mapRemove(source,key)": { "index": 67, "kind": "function", "displayName": 
"Map Remove", "group": "collection", "label": "collection", "required": false, 
"javaType": "Map", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Removes the result of the 
expression from the message body (or expression) which is a map", "ognl": 
false, "suffix": "}" },
+    "max(val...)": { "index": 68, "kind": "function", "displayName": "Maximum 
Number", "group": "number", "label": "number", "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": 69, "kind": "function", "displayName": 
"Message As", "group": "core", "label": "core", "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": 70, "kind": "function", 
"displayName": "Print Message History", "group": "core", "label": "core", 
"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 boolean c [...]
+    "messageTimestamp": { "index": 71, "kind": "function", "displayName": 
"Message Timestamp", "group": "core", "label": "core", "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 timestamp if a t [...]
+    "min(val...)": { "index": 72, "kind": "function", "displayName": "Minimum 
Number", "group": "number", "label": "number", "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": 73, "kind": "function", "displayName": 
"Create Empty Object", "group": "collection", "label": "collection", 
"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`. Us [...]
+    "normalizeWhitespace(exp)": { "index": 74, "kind": "function", 
"displayName": "Normalize Whitespace", "group": "string", "label": "string", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Normalizes the whitespace in the message body (or expression) by cleaning up 
excess whitespaces.", "ognl": false, "suffix": "}" },
+    "not": { "index": 75, "kind": "function", "displayName": "Not", "group": 
"condition", "label": "condition", "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": 76, "kind": "function", "displayName": "Null", "group": 
"other", "label": "other", "required": false, "javaType": "Object", "prefix": 
"${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Returns a null value", "ognl": false, "suffix": "}" },
+    "originalBody": { "index": 77, "kind": "function", "displayName": 
"Original Body", "group": "core", "label": "core", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "The original incoming 
body (only available if allowUseOriginalMessage=true).", "ognl": false, 
"suffix": "}" },
+    "pad(exp,width,separator)": { "index": 78, "kind": "function", 
"displayName": "Pad String", "group": "string", "label": "string", "required": 
false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Pads the expression with extra padding if necessary, according the the total 
width. The separator is by default a space. If the width is negative then 
padding to the right, otherwise to the left.", "ognl" [...]
+    "pretty(exp)": { "index": 79, "kind": "function", "displayName": "Pretty 
Print", "group": "xml", "label": "json,xml", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the expression to 
a String, and attempts to pretty print if JSon or XML, otherwise the expression 
is returned as the String value.", "ognl": false, "suffix": "}" },
+    "prettyBody": { "index": 80, "kind": "function", "displayName": "Pretty 
Body", "group": "xml", "label": "json,xml", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the body to a 
String, and attempts to pretty print if JSon or XML; otherwise the body is 
returned as the String value.", "ognl": false, "suffix": "}" },
+    "sort(exp,reverse)": { "index": 81, "kind": "function", "displayName": 
"Sort", "group": "collection", "label": "collection", "required": false, 
"javaType": "List", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Sorts the message body or 
expression in natural order", "ognl": false, "suffix": "}" },
+    "toPrettyJson(exp)": { "index": 82, "kind": "function", "displayName": "To 
Pretty JSon", "group": "json", "label": "json", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the expression to 
JSon String representation.", "ognl": false, "suffix": "}" },
+    "toPrettyJsonBody": { "index": 83, "kind": "function", "displayName": "To 
Pretty JSon Body", "group": "json", "label": "json", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Converts the body to 
JSon String representation.", "ognl": false, "suffix": "}" },
+    "toJson(exp)": { "index": 84, "kind": "function", "displayName": "To 
JSon", "group": "json", "label": "json", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the expression to 
JSon String representation.", "ognl": false, "suffix": "}" },
+    "toJsonBody": { "index": 85, "kind": "function", "displayName": "To JSon 
Body", "group": "json", "label": "json", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the body to JSon 
String representation.", "ognl": false, "suffix": "}" },
+    "properties:key:default": { "index": 86, "kind": "function", 
"displayName": "Property Placeholder", "group": "core", "label": "core", 
"required": false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Lookup a property placeholder with the given key. If the key does not exist 
nor has a value, then an optional default value can be specified.", "ognl": 
false, "suffix": "}" },
+    "propertiesExist:key": { "index": 87, "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": 88, "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": 89, "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": "}" },
+    "range(min,max)": { "index": 90, "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": 91, "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": 92, "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": 93, "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": 94, "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": 95, "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": 96, "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": 97, "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": 98, "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": 99, "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": 100, "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": 101, "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": 102, "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 numbe [...]
+    "split(exp,separator)": { "index": 103, "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": 104, "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": 105, "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  [...]
+    "substringAfter(exp,before)": { "index": 106, "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": 107, "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": 108, "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": 109, "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": 110, "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": 111, "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": 112, "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": 113, "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": 114, "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": 115, "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": 116, "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": 117, "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": 118, "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": 119, "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 [...]
+    "val(exp)": { "index": 120, "kind": "function", "displayName": "Value", 
"group": "core", "label": "core", "required": false, "javaType": "Object", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Returns the expression as a constant value", 
"ognl": false, "suffix": "}" },
+    "variable.name": { "index": 121, "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": 122, "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": 123, "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": 124, "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 58bd82addfcc..3c970ec29400 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
@@ -255,9 +255,15 @@ in arrays or lists.
 |`empty(kind)` | `<T>` | *Deprecated* Use `createEmpty` instead.
 |`forEach(exp,fun)` | `<List>` | Returns a List containing the values returned 
by the function when applied to each value from the input expression. This 
function is not supported when using csimple.
 |`list(val1,val2,...)` | `List` | The list function creates an 
`java.util.ArrayList` with the given set of values.
-|`listAdd(source,fun)` | `List` | Adds the result of the function to the 
message body (or expression) as a list object.
-|`listRemove(source,fun)` | `List` | Removes the result of the function (use 
int to remove by position index) from the message body (or expression) as a 
list object.
+|`listAdd(fun)` | `List` | Adds the result of the function to the message body 
as a list object.
+|`listAdd(source,fun)` | `List` | Adds the result of the function to the 
source expression as a list object.
+|`listRemove(fun)` | `List` | Removes the result of the function (use int to 
remove by position index) from the message body as a list object.
+|`listRemove(source,fun)` | `List` | Removes the result of the function (use 
int to remove by position index) from the source expression as a list object.
 |`map(key1,value1,...)` | `Map` | The map function creates a 
`java.util.LinkedHashMap` with the given set of pairs.
+|`mapAdd(key,fun)` | `List` | Adds the result of the function to the message 
body as a map object.
+|`mapAdd(source,key,fun)` | `List` | Adds the result of the function to the 
source expression as a map object.
+|`mapRemove(key)` | `List` | Removes the key from the message body as a map 
object.
+|`mapRemove(source,key)` | `List` | Removes the key from the source expression 
as a map object.
 |`createEmpty(kind)` | `<T>` | Creates a new empty object of the given kind. 
The `string` kind creates an empty `String` object. The `list` creates an empty 
`ArrayList`, and `map` creates an empty `LinkedHashMap` object. Use `set` to 
create an empty `java.util.LinkedHashSet`.
 |`reverse(val1,val2,...)` | `List` | Returns a list of all the values, but in 
reverse order.
 |`shuffle(val1,val2,...)` | `List` | Returns a list of all the values shuffled 
in random order.
@@ -291,6 +297,11 @@ of the message body, such as a variable: 
`${listAdd(${variable.myVar},'Hello')}`
 To remove from a list, you use `${listRemove('Hello')}`, or use a number to 
refer to the position `${listRemove(0)}`.
 Use _last_ as a special index to remove the last element: 
`${listRemove(last)}`.
 
+Besides adding to a `List` its also possible to add to a `java.util.Map` with 
the `mapAdd` function. For example if the message body is a `Map` then you can 
add
+something `${mapAdd('country','DK')}`. This will add to the message body. The 
source can also be an expression instead
+of the message body, such as a variable: 
`${mapAdd(${variable.myVar},'country','DK')}`.
+To remove from a list, you use `${mapRemove('country')}`.
+
 The `map` function is similar to the `list` function but for creating a `Map` 
instead where the values are grouped in pairs 2 by 2.
 For example `${map(1,a,2,b,3,c)}` will return a map with 3 elements `{1=a, 
2=b, 3=c}`.
 
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 463cce880f3d..694e09659741 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
@@ -271,6 +271,14 @@ public final class SimpleConstants {
               javaType = "java.util.LinkedHashMap", displayName = "Create Map 
of pairs")
     public static final String MAP = "map(key1,value1,...)";
 
+    @Metadata(description = "Adds the result of the expression to the message 
body (or expression) which is a map",
+              label = "collection", javaType = "Map", displayName = "Map Add")
+    public static final String MAP_ADD = "mapAdd(source,key,exp)";
+
+    @Metadata(description = "Removes the result of the expression from the 
message body (or expression) which is a map",
+              label = "collection", javaType = "Map", displayName = "Map 
Remove")
+    public static final String MAP_REMOVE = "mapRemove(source,key)";
+
     @Metadata(description = "Returns the maximum number from all the values 
(integral numbers only).", label = "number",
               javaType = "long",
               displayName = "Maximum Number")
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 4efc2f44ed75..d7676516c22b 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
@@ -1986,6 +1986,74 @@ public final class SimpleExpressionBuilder {
         };
     }
 
+    /**
+     * Adds the result of the function to the source map
+     */
+    public static Expression mapAddExpression(final String source, final 
String key, final String function) {
+        return new ExpressionAdapter() {
+            private CamelContext context;
+            private Expression exp1;
+            private Expression exp2;
+
+            @Override
+            public void init(CamelContext context) {
+                this.context = context;
+                exp1 = 
context.resolveLanguage("simple").createExpression(source);
+                exp1.init(context);
+                exp2 = 
context.resolveLanguage("simple").createExpression(function);
+                exp2.init(context);
+            }
+
+            @Override
+            public Object evaluate(Exchange exchange) {
+                Map<String, Object> map = exp1.evaluate(exchange, Map.class);
+                if (map != null) {
+                    Object value = exp2.evaluate(exchange, Object.class);
+                    if (value != null) {
+                        map.put(key, value);
+                    }
+                }
+                return map;
+            }
+
+            @Override
+            public String toString() {
+                return "mapAdd(" + source + ", " + key + ", " + function + ")";
+            }
+        };
+    }
+
+    /**
+     * Removes the result of the function from the source map
+     */
+    public static Expression mapRemoveExpression(final String source, final 
String key) {
+        return new ExpressionAdapter() {
+            private CamelContext context;
+            private Expression exp1;
+
+            @Override
+            public void init(CamelContext context) {
+                this.context = context;
+                exp1 = 
context.resolveLanguage("simple").createExpression(source);
+                exp1.init(context);
+            }
+
+            @Override
+            public Object evaluate(Exchange exchange) {
+                Map<String, Object> map = exp1.evaluate(exchange, Map.class);
+                if (map != null) {
+                    map.remove(key);
+                }
+                return map;
+            }
+
+            @Override
+            public String toString() {
+                return "mapRemove(" + source + ", " + key + ")";
+            }
+        };
+    }
+
     /**
      * Filters the values from the source that matches the predicate function
      */
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 065c18f12935..53428c4ba90f 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
@@ -1287,6 +1287,56 @@ public class SimpleFunctionExpression extends 
LiteralExpression {
             String exp2 = 
Arrays.stream(tokens).skip(skip).collect(Collectors.joining(","));
             return SimpleExpressionBuilder.listRemoveExpression(exp1, exp2);
         }
+        // mapAdd function
+        remainder = ifStartsWithReturnRemainder("mapAdd(", function);
+        if (remainder != null) {
+            String values = StringHelper.beforeLast(remainder, ")");
+            if (ObjectHelper.isEmpty(values)) {
+                throw new SimpleParserException(
+                        "Valid syntax: ${mapAdd(key,exp)} or 
${mapAdd(exp,key,exp)} was: " + function, token.getIndex());
+            }
+            String[] tokens = StringQuoteHelper.splitSafeQuote(values, ',', 
false);
+            int skip;
+            String exp1 = "${body}";
+            String key;
+            if (tokens.length > 2) {
+                exp1 = tokens[0];
+                key = tokens[1];
+                skip = 2;
+            } else if (tokens.length == 2) {
+                key = tokens[0];
+                skip = 1;
+            } else {
+                throw new SimpleParserException(
+                        "Valid syntax: ${mapAdd(key,exp)} or 
${mapAdd(exp,key,exp)} was: " + function, token.getIndex());
+            }
+            // the function takes the remainder of the tokens
+            String exp2 = 
Arrays.stream(tokens).skip(skip).collect(Collectors.joining(","));
+            return SimpleExpressionBuilder.mapAddExpression(exp1, key, exp2);
+        }
+        // mapRemove function
+        remainder = ifStartsWithReturnRemainder("mapRemove(", function);
+        if (remainder != null) {
+            String values = StringHelper.beforeLast(remainder, ")");
+            if (ObjectHelper.isEmpty(values)) {
+                throw new SimpleParserException(
+                        "Valid syntax: ${mapRemove(key)} or 
${mapRemove(exp,key)} was: " + function, token.getIndex());
+            }
+            String[] tokens = StringQuoteHelper.splitSafeQuote(values, ',', 
false);
+            if (tokens.length > 2) {
+                throw new SimpleParserException(
+                        "Valid syntax: ${mapRemove(key)} or 
${mapRemove(exp,key)} was: " + function, token.getIndex());
+            }
+            String key;
+            String exp = "${body}";
+            if (tokens.length == 2) {
+                exp = tokens[0];
+                key = tokens[1];
+            } else {
+                key = tokens[0];
+            }
+            return SimpleExpressionBuilder.mapRemoveExpression(exp, key);
+        }
 
         // isEmpty function
         remainder = ifStartsWithReturnRemainder("isEmpty(", 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 333795386dbc..de65f6475292 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
@@ -3902,6 +3902,65 @@ public class SimpleTest extends LanguageTestSupport {
         assertEquals("D", list.get(2));
     }
 
+    @Test
+    public void testMapAdd() {
+        Map body = new HashMap<>();
+        body.put("A", "AAA");
+        body.put("B", "BBB");
+        exchange.getMessage().setBody(body);
+
+        Expression expression = 
context.resolveLanguage("simple").createExpression("${mapAdd('C','CCC')}");
+        Map map = expression.evaluate(exchange, Map.class);
+        assertEquals(3, map.size());
+        assertEquals("AAA", map.get("A"));
+        assertEquals("BBB", map.get("B"));
+        assertEquals("CCC", map.get("C"));
+
+        exchange.getMessage().setHeader("myChar", "DDD");
+        expression = 
context.resolveLanguage("simple").createExpression("${mapAdd('D',${header.myChar})}");
+        map = expression.evaluate(exchange, Map.class);
+        assertEquals(4, map.size());
+        assertEquals("AAA", map.get("A"));
+        assertEquals("BBB", map.get("B"));
+        assertEquals("CCC", map.get("C"));
+        assertEquals("DDD", map.get("D"));
+
+        // two-parameter form: add to a header list instead of body
+        Map headerMap = new HashMap();
+        headerMap.put("X", "XXX");
+        exchange.getMessage().setHeader("myMap", headerMap);
+        expression = 
context.resolveLanguage("simple").createExpression("${mapAdd(${header.myMap},'Y','YYY')}");
+        map = expression.evaluate(exchange, Map.class);
+        assertEquals(2, map.size());
+        assertEquals("XXX", map.get("X"));
+        assertEquals("YYY", map.get("Y"));
+    }
+
+    @Test
+    public void testMapRemove() {
+        Map body = new HashMap<>();
+        body.put("A", "AAA");
+        body.put("B", "BBB");
+        body.put("C", "CCC");
+        exchange.getMessage().setBody(body);
+
+        Expression expression = 
context.resolveLanguage("simple").createExpression("${mapRemove('C')}");
+        Map map = expression.evaluate(exchange, Map.class);
+        assertEquals(2, map.size());
+        assertEquals("AAA", map.get("A"));
+        assertEquals("BBB", map.get("B"));
+
+        // two-parameter form: add to a header list instead of body
+        Map headerMap = new HashMap();
+        headerMap.put("X", "XXX");
+        headerMap.put("Z", "ZZZ");
+        exchange.getMessage().setHeader("myMap", headerMap);
+        expression = 
context.resolveLanguage("simple").createExpression("${mapRemove(${header.myMap},'X')}");
+        map = expression.evaluate(exchange, Map.class);
+        assertEquals(1, map.size());
+        assertEquals("ZZZ", map.get("Z"));
+    }
+
     @Test
     public void testForEach() {
         exchange.getMessage().setBody("Camel,World,Cheese");
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 8b2003334ea9..dca2d08266f9 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
@@ -92,6 +92,8 @@ public class SimpleUtils {
                     "lowercase",
                     "mandatorybodyas",
                     "map",
+                    "mapadd",
+                    "mapremove",
                     "max",
                     "messageas",
                     "messagehistory",

Reply via email to