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 301a5e53e1e6 simple language - add normalize whistespace function
301a5e53e1e6 is described below
commit 301a5e53e1e6c1e6388decc93c2c3f9357eb930a
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri Jan 16 15:53:33 2026 +0100
simple language - add normalize whistespace function
---
.../org/apache/camel/catalog/languages/simple.json | 45 +++++++++++-----------
.../language/csimple/joor/OriginalSimpleTest.java | 22 +++++++++++
.../org/apache/camel/language/simple/simple.json | 45 +++++++++++-----------
.../modules/languages/pages/simple-language.adoc | 2 +
.../camel/language/csimple/CSimpleHelper.java | 13 +++++++
.../camel/language/simple/SimpleConstants.java | 3 ++
.../language/simple/SimpleExpressionBuilder.java | 40 +++++++++++++++++++
.../simple/ast/SimpleFunctionExpression.java | 36 +++++++++++++++++
.../apache/camel/language/simple/SimpleTest.java | 22 +++++++++++
.../java/org/apache/camel/util/StringHelper.java | 38 ++++++++++++++++++
.../org/apache/camel/util/StringHelperTest.java | 18 +++++++++
11 files changed, 240 insertions(+), 44 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 e1a35b5a012e..b08ffa5b4033 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
@@ -79,27 +79,28 @@
"skip(num)": { "index": 53, "kind": "function", "displayName": "Skip First
Items from the Message Body", "group": "function", "label": "function",
"required": false, "javaType": "java.util.Iterator", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The skip function iterates the message body and skips
the first number of items. This can be used with the Splitter EIP to split a
message body and skip the first N number of [...]
"convertTo(exp,type)": { "index": 54, "kind": "function", "displayName":
"Convert To", "group": "function", "label": "function", "required": false,
"javaType": "", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Converts the message body
(or expression) to the specified type.", "ognl": true, "suffix": "}" },
"trim(exp)": { "index": 55, "kind": "function", "displayName": "Trim",
"group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The trim function trims
the message body (or expression) by removing all leading and trailing white
spaces.", "ognl": false, "suffix": "}" },
- "length(exp)": { "index": 56, "kind": "function", "displayName": "Length",
"group": "function", "label": "function", "required": false, "javaType": "int",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "The payload length (number of bytes) of the
message body (or expression).", "ognl": false, "suffix": "}" },
- "size(exp)": { "index": 57, "kind": "function", "displayName": "Size",
"group": "function", "label": "function", "required": false, "javaType": "int",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "The size of the message body (or expression).
If the payload is java.util.Collection or java.util.Map based then the size is
the number of elements; otherwise the payload size in bytes.", "ognl": false,
"suffix": "}" },
- "uppercase(exp)": { "index": 58, "kind": "function", "displayName":
"Uppercase", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Uppercases the message
body (or expression)", "ognl": false, "suffix": "}" },
- "lowercase(exp)": { "index": 59, "kind": "function", "displayName":
"Lowercase", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Lowercases the message
body (or expression)", "ognl": false, "suffix": "}" },
- "concat(exp,exp,separator)": { "index": 60, "kind": "function",
"displayName": "Concat", "group": "function", "label": "function", "required":
false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Performs a string concat using two expressions (message body as default) with
optional separator", "ognl": false, "suffix": "}" },
- "collate(num)": { "index": 61, "kind": "function", "displayName": "Group
Message Body into Sub Lists", "group": "function", "label": "function",
"required": false, "javaType": "java.util.Iterator", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The collate function iterates the message body and
groups the data into sub lists of specified size. This can be used with the
Splitter EIP to split a message body and group\/ba [...]
- "join(separator,prefix,exp)": { "index": 62, "kind": "function",
"displayName": "Join", "group": "function", "label": "function", "required":
false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
join function iterates the message body\/expression and joins the data into a
string. The separator is by default a comma. The prefix is optional. The join
uses the message body as source by default. [...]
- "messageHistory(boolean)": { "index": 63, "kind": "function",
"displayName": "Print Message History", "group": "function", "label":
"function", "required": false, "javaType": "String", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The message history of the current exchange (how it has
been routed). This is similar to the route stack-trace message history the
error handler logs in case of an unhandled exception. The b [...]
- "uuid(type)": { "index": 64, "kind": "function", "displayName": "Generate
UUID", "group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a UUID using the
Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and
`simple` as the type. If no type is given, the default is used. It is also
possible to use a custom `UuidG [...]
- "hash(exp,algorithm)": { "index": 65, "kind": "function", "displayName":
"Compute Hash Value", "group": "function", "label": "function", "required":
false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a hashed value (string in hex decimal) of the message body\/expression
using JDK MessageDigest. The algorithm can be SHA-256 (default) or SHA3-256.",
"ognl": false, "suffix": "}" },
- "empty(type)": { "index": 66, "kind": "function", "displayName": "Create
Empty Object", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Creates a new empty
object (decided by type). Use `string` to create an empty String. Use `list` to
create an empty `java.util.ArrayList`. Use `map` to create an empty
`java.util.LinkedHashMap`.", "ognl": [...]
- "iif(predicate,trueExp,falseExp)": { "index": 67, "kind": "function",
"displayName": "If Then Else", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Evaluates the predicate and returns the value of trueExp or falseExp. This
function is similar to the ternary operator in Java.", "ognl": false, "suffix":
"}" },
- "list(val...)": { "index": 68, "kind": "function", "displayName": "Create
List of values", "group": "function", "label": "function", "required": false,
"javaType": "java.util.ArrayList", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
list function creates an ArrayList with the given set of values.", "ognl":
false, "suffix": "}" },
- "map(key1,value1,...)": { "index": 69, "kind": "function", "displayName":
"Create Map of pairs", "group": "function", "label": "function", "required":
false, "javaType": "java.util.LinkedHashMap", "prefix": "${", "deprecated":
false, "deprecationNote": "", "autowired": false, "secret": false,
"description": "The map function creates a LinkedHashMap with the given set of
pairs.", "ognl": false, "suffix": "}" },
- "attachments": { "index": 70, "kind": "function", "displayName":
"Attachments", "group": "function", "label": "function", "required": false,
"javaType": "java.util.Map", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "All
the attachments as a Map<String,DataHandler.", "ognl": false, "suffix": "}" },
- "attachments.size": { "index": 71, "kind": "function", "displayName":
"Attachments", "group": "function", "label": "function", "required": false,
"javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The number of attachments.
Is 0 if there are no attachments.", "ognl": false, "suffix": "}" },
- "attachmentContentAsText": { "index": 72, "kind": "function",
"displayName": "Attachment Content As Text", "group": "function", "label":
"function", "required": false, "javaType": "String", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The content of the attachment as text (ie String).",
"ognl": false, "suffix": "}" },
- "attachmentContent": { "index": 73, "kind": "function", "displayName":
"Attachment Content", "group": "function", "label": "function", "required":
false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
content of the attachment", "ognl": false, "suffix": "}" },
- "attachmentContentAs(type)": { "index": 74, "kind": "function",
"displayName": "Attachment Content As", "group": "function", "label":
"function", "required": false, "javaType": "Object", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The content of the attachment, converted to the given
type.", "ognl": false, "suffix": "}" },
- "attachmentHeader(key,name)": { "index": 75, "kind": "function",
"displayName": "Attachment Header", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
attachment header with the given name.", "ognl": false, "suffix": "}" },
- "attachmentHeader(key,name,type)": { "index": 76, "kind": "function",
"displayName": "Attachment Header", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
attachment header with the given name, converted to the given type.", "ognl":
false, "suffix": "}" },
- "attachment(key)": { "index": 77, "kind": "function", "displayName":
"Attachment", "group": "function", "label": "function", "required": false,
"javaType": "jakarta.activation.DataHandler", "prefix": "${", "deprecated":
false, "deprecationNote": "", "autowired": false, "secret": false,
"description": "The DataHandler for the given attachment.", "ognl": true,
"suffix": "}" }
+ "normalizeWhitespace(exp)": { "index": 56, "kind": "function",
"displayName": "Normalize Whitspace", "group": "function", "label": "function",
"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": "}" },
+ "length(exp)": { "index": 57, "kind": "function", "displayName": "Length",
"group": "function", "label": "function", "required": false, "javaType": "int",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "The payload length (number of bytes) of the
message body (or expression).", "ognl": false, "suffix": "}" },
+ "size(exp)": { "index": 58, "kind": "function", "displayName": "Size",
"group": "function", "label": "function", "required": false, "javaType": "int",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "The size of the message body (or expression).
If the payload is java.util.Collection or java.util.Map based then the size is
the number of elements; otherwise the payload size in bytes.", "ognl": false,
"suffix": "}" },
+ "uppercase(exp)": { "index": 59, "kind": "function", "displayName":
"Uppercase", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Uppercases the message
body (or expression)", "ognl": false, "suffix": "}" },
+ "lowercase(exp)": { "index": 60, "kind": "function", "displayName":
"Lowercase", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Lowercases the message
body (or expression)", "ognl": false, "suffix": "}" },
+ "concat(exp,exp,separator)": { "index": 61, "kind": "function",
"displayName": "Concat", "group": "function", "label": "function", "required":
false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Performs a string concat using two expressions (message body as default) with
optional separator", "ognl": false, "suffix": "}" },
+ "collate(num)": { "index": 62, "kind": "function", "displayName": "Group
Message Body into Sub Lists", "group": "function", "label": "function",
"required": false, "javaType": "java.util.Iterator", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The collate function iterates the message body and
groups the data into sub lists of specified size. This can be used with the
Splitter EIP to split a message body and group\/ba [...]
+ "join(separator,prefix,exp)": { "index": 63, "kind": "function",
"displayName": "Join", "group": "function", "label": "function", "required":
false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
join function iterates the message body\/expression and joins the data into a
string. The separator is by default a comma. The prefix is optional. The join
uses the message body as source by default. [...]
+ "messageHistory(boolean)": { "index": 64, "kind": "function",
"displayName": "Print Message History", "group": "function", "label":
"function", "required": false, "javaType": "String", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The message history of the current exchange (how it has
been routed). This is similar to the route stack-trace message history the
error handler logs in case of an unhandled exception. The b [...]
+ "uuid(type)": { "index": 65, "kind": "function", "displayName": "Generate
UUID", "group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a UUID using the
Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and
`simple` as the type. If no type is given, the default is used. It is also
possible to use a custom `UuidG [...]
+ "hash(exp,algorithm)": { "index": 66, "kind": "function", "displayName":
"Compute Hash Value", "group": "function", "label": "function", "required":
false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a hashed value (string in hex decimal) of the message body\/expression
using JDK MessageDigest. The algorithm can be SHA-256 (default) or SHA3-256.",
"ognl": false, "suffix": "}" },
+ "empty(type)": { "index": 67, "kind": "function", "displayName": "Create
Empty Object", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Creates a new empty
object (decided by type). Use `string` to create an empty String. Use `list` to
create an empty `java.util.ArrayList`. Use `map` to create an empty
`java.util.LinkedHashMap`.", "ognl": [...]
+ "iif(predicate,trueExp,falseExp)": { "index": 68, "kind": "function",
"displayName": "If Then Else", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Evaluates the predicate and returns the value of trueExp or falseExp. This
function is similar to the ternary operator in Java.", "ognl": false, "suffix":
"}" },
+ "list(val...)": { "index": 69, "kind": "function", "displayName": "Create
List of values", "group": "function", "label": "function", "required": false,
"javaType": "java.util.ArrayList", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
list function creates an ArrayList with the given set of values.", "ognl":
false, "suffix": "}" },
+ "map(key1,value1,...)": { "index": 70, "kind": "function", "displayName":
"Create Map of pairs", "group": "function", "label": "function", "required":
false, "javaType": "java.util.LinkedHashMap", "prefix": "${", "deprecated":
false, "deprecationNote": "", "autowired": false, "secret": false,
"description": "The map function creates a LinkedHashMap with the given set of
pairs.", "ognl": false, "suffix": "}" },
+ "attachments": { "index": 71, "kind": "function", "displayName":
"Attachments", "group": "function", "label": "function", "required": false,
"javaType": "java.util.Map", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "All
the attachments as a Map<String,DataHandler.", "ognl": false, "suffix": "}" },
+ "attachments.size": { "index": 72, "kind": "function", "displayName":
"Attachments", "group": "function", "label": "function", "required": false,
"javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The number of attachments.
Is 0 if there are no attachments.", "ognl": false, "suffix": "}" },
+ "attachmentContentAsText": { "index": 73, "kind": "function",
"displayName": "Attachment Content As Text", "group": "function", "label":
"function", "required": false, "javaType": "String", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The content of the attachment as text (ie String).",
"ognl": false, "suffix": "}" },
+ "attachmentContent": { "index": 74, "kind": "function", "displayName":
"Attachment Content", "group": "function", "label": "function", "required":
false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
content of the attachment", "ognl": false, "suffix": "}" },
+ "attachmentContentAs(type)": { "index": 75, "kind": "function",
"displayName": "Attachment Content As", "group": "function", "label":
"function", "required": false, "javaType": "Object", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The content of the attachment, converted to the given
type.", "ognl": false, "suffix": "}" },
+ "attachmentHeader(key,name)": { "index": 76, "kind": "function",
"displayName": "Attachment Header", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
attachment header with the given name.", "ognl": false, "suffix": "}" },
+ "attachmentHeader(key,name,type)": { "index": 77, "kind": "function",
"displayName": "Attachment Header", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
attachment header with the given name, converted to the given type.", "ognl":
false, "suffix": "}" },
+ "attachment(key)": { "index": 78, "kind": "function", "displayName":
"Attachment", "group": "function", "label": "function", "required": false,
"javaType": "jakarta.activation.DataHandler", "prefix": "${", "deprecated":
false, "deprecationNote": "", "autowired": false, "secret": false,
"description": "The DataHandler for the given attachment.", "ognl": true,
"suffix": "}" }
}
}
diff --git
a/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java
b/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java
index 485f1a20a4ea..7e5454cbb6cd 100644
---
a/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java
+++
b/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java
@@ -2543,6 +2543,28 @@ public class OriginalSimpleTest extends
LanguageTestSupport {
assertEquals("Carlsberg", s);
}
+ @Test
+ public void testNormalizeWhitespace() {
+ exchange.getMessage().setBody(" Hello big World ");
+
+ Expression expression =
context.resolveLanguage("csimple").createExpression("${normalizeWhitespace()}");
+ String s = expression.evaluate(exchange, String.class);
+ assertEquals("Hello big World", s);
+
+ expression =
context.resolveLanguage("csimple").createExpression("${normalizeWhitespace(${body})}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("Hello big World", s);
+
+ expression =
context.resolveLanguage("csimple").createExpression("${normalizeWhitespace(' Hi
from me ')}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("Hi from me", s);
+
+ exchange.getMessage().setHeader("beer", " Carlsberg is a beer
");
+ expression =
context.resolveLanguage("csimple").createExpression("${normalizeWhitespace(${header.beer})}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("Carlsberg is a beer", s);
+ }
+
@Test
public void testConcat() {
exchange.getMessage().setBody("Hello");
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 e1a35b5a012e..b08ffa5b4033 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
@@ -79,27 +79,28 @@
"skip(num)": { "index": 53, "kind": "function", "displayName": "Skip First
Items from the Message Body", "group": "function", "label": "function",
"required": false, "javaType": "java.util.Iterator", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The skip function iterates the message body and skips
the first number of items. This can be used with the Splitter EIP to split a
message body and skip the first N number of [...]
"convertTo(exp,type)": { "index": 54, "kind": "function", "displayName":
"Convert To", "group": "function", "label": "function", "required": false,
"javaType": "", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Converts the message body
(or expression) to the specified type.", "ognl": true, "suffix": "}" },
"trim(exp)": { "index": 55, "kind": "function", "displayName": "Trim",
"group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The trim function trims
the message body (or expression) by removing all leading and trailing white
spaces.", "ognl": false, "suffix": "}" },
- "length(exp)": { "index": 56, "kind": "function", "displayName": "Length",
"group": "function", "label": "function", "required": false, "javaType": "int",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "The payload length (number of bytes) of the
message body (or expression).", "ognl": false, "suffix": "}" },
- "size(exp)": { "index": 57, "kind": "function", "displayName": "Size",
"group": "function", "label": "function", "required": false, "javaType": "int",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "The size of the message body (or expression).
If the payload is java.util.Collection or java.util.Map based then the size is
the number of elements; otherwise the payload size in bytes.", "ognl": false,
"suffix": "}" },
- "uppercase(exp)": { "index": 58, "kind": "function", "displayName":
"Uppercase", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Uppercases the message
body (or expression)", "ognl": false, "suffix": "}" },
- "lowercase(exp)": { "index": 59, "kind": "function", "displayName":
"Lowercase", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Lowercases the message
body (or expression)", "ognl": false, "suffix": "}" },
- "concat(exp,exp,separator)": { "index": 60, "kind": "function",
"displayName": "Concat", "group": "function", "label": "function", "required":
false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Performs a string concat using two expressions (message body as default) with
optional separator", "ognl": false, "suffix": "}" },
- "collate(num)": { "index": 61, "kind": "function", "displayName": "Group
Message Body into Sub Lists", "group": "function", "label": "function",
"required": false, "javaType": "java.util.Iterator", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The collate function iterates the message body and
groups the data into sub lists of specified size. This can be used with the
Splitter EIP to split a message body and group\/ba [...]
- "join(separator,prefix,exp)": { "index": 62, "kind": "function",
"displayName": "Join", "group": "function", "label": "function", "required":
false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
join function iterates the message body\/expression and joins the data into a
string. The separator is by default a comma. The prefix is optional. The join
uses the message body as source by default. [...]
- "messageHistory(boolean)": { "index": 63, "kind": "function",
"displayName": "Print Message History", "group": "function", "label":
"function", "required": false, "javaType": "String", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The message history of the current exchange (how it has
been routed). This is similar to the route stack-trace message history the
error handler logs in case of an unhandled exception. The b [...]
- "uuid(type)": { "index": 64, "kind": "function", "displayName": "Generate
UUID", "group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a UUID using the
Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and
`simple` as the type. If no type is given, the default is used. It is also
possible to use a custom `UuidG [...]
- "hash(exp,algorithm)": { "index": 65, "kind": "function", "displayName":
"Compute Hash Value", "group": "function", "label": "function", "required":
false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a hashed value (string in hex decimal) of the message body\/expression
using JDK MessageDigest. The algorithm can be SHA-256 (default) or SHA3-256.",
"ognl": false, "suffix": "}" },
- "empty(type)": { "index": 66, "kind": "function", "displayName": "Create
Empty Object", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Creates a new empty
object (decided by type). Use `string` to create an empty String. Use `list` to
create an empty `java.util.ArrayList`. Use `map` to create an empty
`java.util.LinkedHashMap`.", "ognl": [...]
- "iif(predicate,trueExp,falseExp)": { "index": 67, "kind": "function",
"displayName": "If Then Else", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Evaluates the predicate and returns the value of trueExp or falseExp. This
function is similar to the ternary operator in Java.", "ognl": false, "suffix":
"}" },
- "list(val...)": { "index": 68, "kind": "function", "displayName": "Create
List of values", "group": "function", "label": "function", "required": false,
"javaType": "java.util.ArrayList", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
list function creates an ArrayList with the given set of values.", "ognl":
false, "suffix": "}" },
- "map(key1,value1,...)": { "index": 69, "kind": "function", "displayName":
"Create Map of pairs", "group": "function", "label": "function", "required":
false, "javaType": "java.util.LinkedHashMap", "prefix": "${", "deprecated":
false, "deprecationNote": "", "autowired": false, "secret": false,
"description": "The map function creates a LinkedHashMap with the given set of
pairs.", "ognl": false, "suffix": "}" },
- "attachments": { "index": 70, "kind": "function", "displayName":
"Attachments", "group": "function", "label": "function", "required": false,
"javaType": "java.util.Map", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "All
the attachments as a Map<String,DataHandler.", "ognl": false, "suffix": "}" },
- "attachments.size": { "index": 71, "kind": "function", "displayName":
"Attachments", "group": "function", "label": "function", "required": false,
"javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The number of attachments.
Is 0 if there are no attachments.", "ognl": false, "suffix": "}" },
- "attachmentContentAsText": { "index": 72, "kind": "function",
"displayName": "Attachment Content As Text", "group": "function", "label":
"function", "required": false, "javaType": "String", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The content of the attachment as text (ie String).",
"ognl": false, "suffix": "}" },
- "attachmentContent": { "index": 73, "kind": "function", "displayName":
"Attachment Content", "group": "function", "label": "function", "required":
false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
content of the attachment", "ognl": false, "suffix": "}" },
- "attachmentContentAs(type)": { "index": 74, "kind": "function",
"displayName": "Attachment Content As", "group": "function", "label":
"function", "required": false, "javaType": "Object", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The content of the attachment, converted to the given
type.", "ognl": false, "suffix": "}" },
- "attachmentHeader(key,name)": { "index": 75, "kind": "function",
"displayName": "Attachment Header", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
attachment header with the given name.", "ognl": false, "suffix": "}" },
- "attachmentHeader(key,name,type)": { "index": 76, "kind": "function",
"displayName": "Attachment Header", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
attachment header with the given name, converted to the given type.", "ognl":
false, "suffix": "}" },
- "attachment(key)": { "index": 77, "kind": "function", "displayName":
"Attachment", "group": "function", "label": "function", "required": false,
"javaType": "jakarta.activation.DataHandler", "prefix": "${", "deprecated":
false, "deprecationNote": "", "autowired": false, "secret": false,
"description": "The DataHandler for the given attachment.", "ognl": true,
"suffix": "}" }
+ "normalizeWhitespace(exp)": { "index": 56, "kind": "function",
"displayName": "Normalize Whitspace", "group": "function", "label": "function",
"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": "}" },
+ "length(exp)": { "index": 57, "kind": "function", "displayName": "Length",
"group": "function", "label": "function", "required": false, "javaType": "int",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "The payload length (number of bytes) of the
message body (or expression).", "ognl": false, "suffix": "}" },
+ "size(exp)": { "index": 58, "kind": "function", "displayName": "Size",
"group": "function", "label": "function", "required": false, "javaType": "int",
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "description": "The size of the message body (or expression).
If the payload is java.util.Collection or java.util.Map based then the size is
the number of elements; otherwise the payload size in bytes.", "ognl": false,
"suffix": "}" },
+ "uppercase(exp)": { "index": 59, "kind": "function", "displayName":
"Uppercase", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Uppercases the message
body (or expression)", "ognl": false, "suffix": "}" },
+ "lowercase(exp)": { "index": 60, "kind": "function", "displayName":
"Lowercase", "group": "function", "label": "function", "required": false,
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Lowercases the message
body (or expression)", "ognl": false, "suffix": "}" },
+ "concat(exp,exp,separator)": { "index": 61, "kind": "function",
"displayName": "Concat", "group": "function", "label": "function", "required":
false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Performs a string concat using two expressions (message body as default) with
optional separator", "ognl": false, "suffix": "}" },
+ "collate(num)": { "index": 62, "kind": "function", "displayName": "Group
Message Body into Sub Lists", "group": "function", "label": "function",
"required": false, "javaType": "java.util.Iterator", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The collate function iterates the message body and
groups the data into sub lists of specified size. This can be used with the
Splitter EIP to split a message body and group\/ba [...]
+ "join(separator,prefix,exp)": { "index": 63, "kind": "function",
"displayName": "Join", "group": "function", "label": "function", "required":
false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
join function iterates the message body\/expression and joins the data into a
string. The separator is by default a comma. The prefix is optional. The join
uses the message body as source by default. [...]
+ "messageHistory(boolean)": { "index": 64, "kind": "function",
"displayName": "Print Message History", "group": "function", "label":
"function", "required": false, "javaType": "String", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The message history of the current exchange (how it has
been routed). This is similar to the route stack-trace message history the
error handler logs in case of an unhandled exception. The b [...]
+ "uuid(type)": { "index": 65, "kind": "function", "displayName": "Generate
UUID", "group": "function", "label": "function", "required": false, "javaType":
"String", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "Returns a UUID using the
Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and
`simple` as the type. If no type is given, the default is used. It is also
possible to use a custom `UuidG [...]
+ "hash(exp,algorithm)": { "index": 66, "kind": "function", "displayName":
"Compute Hash Value", "group": "function", "label": "function", "required":
false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Returns a hashed value (string in hex decimal) of the message body\/expression
using JDK MessageDigest. The algorithm can be SHA-256 (default) or SHA3-256.",
"ognl": false, "suffix": "}" },
+ "empty(type)": { "index": 67, "kind": "function", "displayName": "Create
Empty Object", "group": "function", "label": "function", "required": false,
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "description": "Creates a new empty
object (decided by type). Use `string` to create an empty String. Use `list` to
create an empty `java.util.ArrayList`. Use `map` to create an empty
`java.util.LinkedHashMap`.", "ognl": [...]
+ "iif(predicate,trueExp,falseExp)": { "index": 68, "kind": "function",
"displayName": "If Then Else", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description":
"Evaluates the predicate and returns the value of trueExp or falseExp. This
function is similar to the ternary operator in Java.", "ognl": false, "suffix":
"}" },
+ "list(val...)": { "index": 69, "kind": "function", "displayName": "Create
List of values", "group": "function", "label": "function", "required": false,
"javaType": "java.util.ArrayList", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
list function creates an ArrayList with the given set of values.", "ognl":
false, "suffix": "}" },
+ "map(key1,value1,...)": { "index": 70, "kind": "function", "displayName":
"Create Map of pairs", "group": "function", "label": "function", "required":
false, "javaType": "java.util.LinkedHashMap", "prefix": "${", "deprecated":
false, "deprecationNote": "", "autowired": false, "secret": false,
"description": "The map function creates a LinkedHashMap with the given set of
pairs.", "ognl": false, "suffix": "}" },
+ "attachments": { "index": 71, "kind": "function", "displayName":
"Attachments", "group": "function", "label": "function", "required": false,
"javaType": "java.util.Map", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "All
the attachments as a Map<String,DataHandler.", "ognl": false, "suffix": "}" },
+ "attachments.size": { "index": 72, "kind": "function", "displayName":
"Attachments", "group": "function", "label": "function", "required": false,
"javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "description": "The number of attachments.
Is 0 if there are no attachments.", "ognl": false, "suffix": "}" },
+ "attachmentContentAsText": { "index": 73, "kind": "function",
"displayName": "Attachment Content As Text", "group": "function", "label":
"function", "required": false, "javaType": "String", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The content of the attachment as text (ie String).",
"ognl": false, "suffix": "}" },
+ "attachmentContent": { "index": 74, "kind": "function", "displayName":
"Attachment Content", "group": "function", "label": "function", "required":
false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
content of the attachment", "ognl": false, "suffix": "}" },
+ "attachmentContentAs(type)": { "index": 75, "kind": "function",
"displayName": "Attachment Content As", "group": "function", "label":
"function", "required": false, "javaType": "Object", "prefix": "${",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The content of the attachment, converted to the given
type.", "ognl": false, "suffix": "}" },
+ "attachmentHeader(key,name)": { "index": 76, "kind": "function",
"displayName": "Attachment Header", "group": "function", "label": "function",
"required": false, "javaType": "String", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
attachment header with the given name.", "ognl": false, "suffix": "}" },
+ "attachmentHeader(key,name,type)": { "index": 77, "kind": "function",
"displayName": "Attachment Header", "group": "function", "label": "function",
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "description": "The
attachment header with the given name, converted to the given type.", "ognl":
false, "suffix": "}" },
+ "attachment(key)": { "index": 78, "kind": "function", "displayName":
"Attachment", "group": "function", "label": "function", "required": false,
"javaType": "jakarta.activation.DataHandler", "prefix": "${", "deprecated":
false, "deprecationNote": "", "autowired": false, "secret": false,
"description": "The DataHandler for the given attachment.", "ognl": true,
"suffix": "}" }
}
}
diff --git
a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
index 6e64c7c04abf..9238e4ef2cf4 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
@@ -282,6 +282,8 @@ similar to the collate method in Groovy.
|capitalize(exp) |String |Capitalizes the message body/expression as a String
value (upper case every words)
+|normalizeWhitespace(exp) |String |Normalizes the whitespace in the message
body (or expression) by cleaning up excess whitespaces.
+
|skip(number) |Iterator |The skip function iterates the message body and skips
the first number of items. This can be used with the
Splitter EIP to split a message body and skip the first N number of items.
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java
index e294ef431792..c86899a44c28 100644
---
a/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java
@@ -840,6 +840,19 @@ public final class CSimpleHelper {
return body;
}
+ public static String normalizeWhitespace(Exchange exchange, Object value) {
+ String body;
+ if (value != null) {
+ body =
exchange.getContext().getTypeConverter().tryConvertTo(String.class, exchange,
value);
+ } else {
+ body = exchange.getMessage().getBody(String.class);
+ }
+ if (body != null) {
+ body = StringHelper.normalizeWhitespace(body);
+ }
+ return body;
+ }
+
public static String concat(Exchange exchange, Object left, Object right,
Object separator) {
String val1 =
exchange.getContext().getTypeConverter().tryConvertTo(String.class, exchange,
left);
String val2 =
exchange.getContext().getTypeConverter().tryConvertTo(String.class, exchange,
right);
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 4c780bce12c2..1c0ce7a142f4 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
@@ -205,6 +205,9 @@ public final class SimpleConstants {
@Metadata(description = "The trim function trims the message body (or
expression) by removing all leading and trailing white spaces.",
label = "function", javaType = "String", displayName = "Trim")
public static final String TRIM = "trim(exp)";
+ @Metadata(description = "Normalizes the whitespace in the message body (or
expression) by cleaning up excess whitespaces.",
+ label = "function", javaType = "String", displayName =
"Normalize Whitspace")
+ public static final String NORMALIZE_WHITESPACE =
"normalizeWhitespace(exp)";
@Metadata(description = "The payload length (number of bytes) of the
message body (or expression).",
label = "function", javaType = "int", displayName = "Length")
public static final String LENGTH = "length(exp)";
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 362e499a58d8..4fb86dd14caa 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
@@ -288,6 +288,46 @@ public final class SimpleExpressionBuilder {
};
}
+ /**
+ * Normalizes the whitespaces in the given expressions (uses message body
if expression is null)
+ */
+ public static Expression normalizeWhitespaceExpression(final String
expression) {
+ return new ExpressionAdapter() {
+ private Expression exp;
+
+ @Override
+ public void init(CamelContext context) {
+ if (expression != null) {
+ exp =
context.resolveLanguage("simple").createExpression(expression);
+ exp.init(context);
+ }
+ }
+
+ @Override
+ public Object evaluate(Exchange exchange) {
+ String value;
+ if (exp != null) {
+ value = exp.evaluate(exchange, String.class);
+ } else {
+ value = exchange.getMessage().getBody(String.class);
+ }
+ if (value != null) {
+ value = StringHelper.normalizeWhitespace(value);
+ }
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ if (expression != null) {
+ return "normalizeWhitespace(" + expression + ")";
+ } else {
+ return "normalizeWhitespace()";
+ }
+ }
+ };
+ }
+
/**
* Capitalizes the given expressions (uses message body if expression is
null)
*/
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 80fb0c9622fe..7c6ac3bf931c 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
@@ -961,6 +961,17 @@ public class SimpleFunctionExpression extends
LiteralExpression {
return SimpleExpressionBuilder.trimExpression(exp);
}
+ // normalizeWhitespace function
+ remainder = ifStartsWithReturnRemainder("normalizeWhitespace(",
function);
+ if (remainder != null) {
+ String exp = null;
+ String value = StringHelper.beforeLast(remainder, ")");
+ if (ObjectHelper.isNotEmpty(value)) {
+ exp = StringHelper.removeQuotes(value);
+ }
+ return SimpleExpressionBuilder.normalizeWhitespaceExpression(exp);
+ }
+
// capitalize
remainder = ifStartsWithReturnRemainder("capitalize(", function);
if (remainder != null) {
@@ -2324,6 +2335,31 @@ public class SimpleFunctionExpression extends
LiteralExpression {
return "Object o = " + exp + ";\n return
capitalize(exchange, o);";
}
+ // normalizeWhitespace function
+ remainder = ifStartsWithReturnRemainder("normalizeWhitespace(",
function);
+ if (remainder != null) {
+ String exp = null;
+ String values = StringHelper.beforeLast(remainder, ")");
+ if (ObjectHelper.isNotEmpty(values)) {
+ String[] tokens = codeSplitSafe(values, ',', true, true);
+ if (tokens.length != 1) {
+ throw new SimpleParserException(
+ "Valid syntax: ${normalizeWhitespace(exp)} was: "
+ function, token.getIndex());
+ }
+ // single quotes should be double quotes
+ String s = tokens[0];
+ if (StringHelper.isSingleQuoted(s)) {
+ s = StringHelper.removeLeadingAndEndingQuotes(s);
+ s = StringQuoteHelper.doubleQuote(s);
+ }
+ exp = s;
+ }
+ if (ObjectHelper.isEmpty(exp)) {
+ exp = "null";
+ }
+ return "Object o = " + exp + ";\n return
normalizeWhitespace(exchange, o);";
+ }
+
// concat function
remainder = ifStartsWithReturnRemainder("concat(", function);
if (remainder != null) {
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
index cf87eba403be..2dcc79489dcb 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
@@ -2667,6 +2667,28 @@ public class SimpleTest extends LanguageTestSupport {
assertEquals("Carlsberg", s);
}
+ @Test
+ public void testNormalizeWhitespace() {
+ exchange.getMessage().setBody(" Hello big World ");
+
+ Expression expression =
context.resolveLanguage("simple").createExpression("${normalizeWhitespace()}");
+ String s = expression.evaluate(exchange, String.class);
+ assertEquals("Hello big World", s);
+
+ expression =
context.resolveLanguage("simple").createExpression("${normalizeWhitespace(${body})}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("Hello big World", s);
+
+ expression =
context.resolveLanguage("simple").createExpression("${normalizeWhitespace(' Hi
from me ')}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("Hi from me", s);
+
+ exchange.getMessage().setHeader("beer", " Carlsberg is a beer
");
+ expression =
context.resolveLanguage("simple").createExpression("${normalizeWhitespace(${header.beer})}");
+ s = expression.evaluate(exchange, String.class);
+ assertEquals("Carlsberg is a beer", s);
+ }
+
@Test
public void testSubstringBefore() {
exchange.getMessage().setBody("Hello World");
diff --git
a/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
b/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
index 7003c526ad57..9cc67f447cb8 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/StringHelper.java
@@ -1422,6 +1422,9 @@ public final class StringHelper {
}
}
+ /**
+ * Is the given string only numbers
+ */
public static boolean isDigit(String s) {
for (char ch : s.toCharArray()) {
if (!Character.isDigit(ch)) {
@@ -1431,6 +1434,9 @@ public final class StringHelper {
return true;
}
+ /**
+ * Converts the bytes to hex decimal
+ */
public static String bytesToHex(byte[] hash) {
StringBuilder sb = new StringBuilder(2 * hash.length);
for (byte b : hash) {
@@ -1443,4 +1449,36 @@ public final class StringHelper {
return sb.toString();
}
+ /**
+ * Normalizes the whitespaces by removing any excess spaces so there are
only at most a single whitespace.
+ */
+ public static String normalizeWhitespace(String text) {
+ if (text == null) {
+ return null;
+ }
+ if (text.isBlank()) {
+ return "";
+ }
+
+ // must have at least double spaces
+ if (!text.contains(" ")) {
+ return text.trim();
+ }
+
+ StringBuilder sb = new StringBuilder(text.length());
+ final char[] chars = text.toCharArray();
+ for (int i = 1; i < chars.length; i++) {
+ char prev = chars[i - 1];
+ char ch = chars[i];
+ if (Character.isWhitespace(ch) && Character.isWhitespace(prev)) {
+ continue;
+ }
+ if (i == 1) {
+ sb.append(prev);
+ }
+ sb.append(ch);
+ }
+ return sb.toString().trim();
+ }
+
}
diff --git
a/core/camel-util/src/test/java/org/apache/camel/util/StringHelperTest.java
b/core/camel-util/src/test/java/org/apache/camel/util/StringHelperTest.java
index d12b58010ea7..1f24516e0224 100644
--- a/core/camel-util/src/test/java/org/apache/camel/util/StringHelperTest.java
+++ b/core/camel-util/src/test/java/org/apache/camel/util/StringHelperTest.java
@@ -617,6 +617,24 @@ public class StringHelperTest {
assertEquals("Hello World How Are You",
StringHelper.capitalizeAll("hello world how are you"));
}
+ @Test
+ public void testNormalizeWhitespace() {
+ assertNull(StringHelper.normalizeWhitespace(null));
+ assertEquals("", StringHelper.normalizeWhitespace(""));
+ assertEquals("", StringHelper.normalizeWhitespace(" "));
+ assertEquals("", StringHelper.normalizeWhitespace(" "));
+ assertEquals("", StringHelper.normalizeWhitespace("
"));
+ assertEquals("A", StringHelper.normalizeWhitespace(" A
"));
+ assertEquals("Hello World How Are You",
StringHelper.normalizeWhitespace("Hello World How Are You"));
+ assertEquals("Hello World", StringHelper.normalizeWhitespace(" Hello
World "));
+ assertEquals("Hello World", StringHelper.normalizeWhitespace(" Hello
World "));
+ assertEquals("Hello World", StringHelper.normalizeWhitespace(" Hello
World "));
+ assertEquals("Hello Big World", StringHelper.normalizeWhitespace("
Hello Big World "));
+ assertEquals("Hello Big World",
StringHelper.normalizeWhitespace("Hello Big World"));
+ assertEquals("Hello Big World", StringHelper.normalizeWhitespace("
Hello Big World"));
+ assertEquals("Hello Big World", StringHelper.normalizeWhitespace("
Hello Big World "));
+ }
+
@Test
public void testStartsWithIgnoreCase() {
assertTrue(StringHelper.startsWithIgnoreCase(null, null));