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 d1a85a47bc07 camel-core - Add floor/ceil function to simple language
d1a85a47bc07 is described below

commit d1a85a47bc0727503f3f2c68435be580e38b1477
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Jan 20 08:18:42 2026 +0100

    camel-core - Add floor/ceil function to simple language
---
 .../org/apache/camel/catalog/languages/simple.json | 22 +++---
 .../language/csimple/joor/OriginalSimpleTest.java  | 68 ++++++++++++++++++
 .../org/apache/camel/language/simple/simple.json   | 22 +++---
 .../modules/languages/pages/simple-language.adoc   |  5 ++
 .../camel/language/csimple/CSimpleHelper.java      | 28 ++++++++
 .../camel/language/simple/SimpleConstants.java     |  6 ++
 .../language/simple/SimpleExpressionBuilder.java   | 84 ++++++++++++++++++++++
 .../simple/ast/SimpleFunctionExpression.java       | 66 +++++++++++++++++
 .../apache/camel/language/simple/SimpleTest.java   | 76 ++++++++++++++++++++
 9 files changed, 357 insertions(+), 20 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 8c653a379aae..db79f38ceb37 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
@@ -97,15 +97,17 @@
     "list(val...)": { "index": 71, "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": 72, "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": "}" },
     "abs(exp)": { "index": 73, "kind": "function", "displayName": "Absolute 
Number", "group": "function", "label": "function", "required": false, 
"javaType": "Long", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the message body 
(or expression) to a long number and return the absolute value.", "ognl": 
false, "suffix": "}" },
-    "attachments": { "index": 74, "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": 75, "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": 76, "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": 77, "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": 78, "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": 79, "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": 80, "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": 81, "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": "}" },
-    "base64Encode(exp)": { "index": 82, "kind": "function", "displayName": 
"Base64 Encode", "group": "function", "label": "function", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Base64 encodes the 
message body (or expression)", "ognl": false, "suffix": "}" },
-    "base64Decode(exp)": { "index": 83, "kind": "function", "displayName": 
"Base64 Decode", "group": "function", "label": "function", "required": false, 
"javaType": "byte[]", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Base64 decodes the 
message body (or expression)", "ognl": false, "suffix": "}" }
+    "ceil(exp)": { "index": 74, "kind": "function", "displayName": "Ceil 
Number", "group": "function", "label": "function", "required": false, 
"javaType": "Integer", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Converts the message 
body (or expression) to a floating number and return the ceil value (rounded up 
to nearest integer).", "ognl": false, "suffix": "}" },
+    "floor(exp)": { "index": 75, "kind": "function", "displayName": "Floor 
Number", "group": "function", "label": "function", "required": false, 
"javaType": "Integer", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Converts the message 
body (or expression) to a floating number and return the floor value (rounded 
down to nearest integer).", "ognl": false, "suffix": "}" },
+    "attachments": { "index": 76, "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": 77, "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": 78, "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": 79, "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": 80, "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": 81, "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": 82, "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": 83, "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": "}" },
+    "base64Encode(exp)": { "index": 84, "kind": "function", "displayName": 
"Base64 Encode", "group": "function", "label": "function", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Base64 encodes the 
message body (or expression)", "ognl": false, "suffix": "}" },
+    "base64Decode(exp)": { "index": 85, "kind": "function", "displayName": 
"Base64 Decode", "group": "function", "label": "function", "required": false, 
"javaType": "byte[]", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Base64 decodes the 
message body (or expression)", "ognl": false, "suffix": "}" }
   }
 }
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 59e489de5caf..398ea61628b7 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
@@ -2721,6 +2721,74 @@ public class OriginalSimpleTest extends 
LanguageTestSupport {
         assertEquals("222", s);
     }
 
+    @Test
+    public void testFloor() {
+        exchange.getMessage().setBody("5.3");
+
+        Expression expression = 
context.resolveLanguage("csimple").createExpression("${floor()}");
+        int i = expression.evaluate(exchange, Integer.class);
+        assertEquals(5, i);
+
+        expression = 
context.resolveLanguage("csimple").createExpression("${floor(${body})}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(5, i);
+
+        expression = 
context.resolveLanguage("csimple").createExpression("${floor(6.8)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(6, i);
+
+        expression = 
context.resolveLanguage("csimple").createExpression("${floor(-12.9)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(-13, i);
+
+        expression = 
context.resolveLanguage("csimple").createExpression("${floor(0.0)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(0, i);
+
+        exchange.getMessage().setHeader("myNum", "234.56");
+        expression = 
context.resolveLanguage("csimple").createExpression("${floor(${header.myNum})}");
+        String s = expression.evaluate(exchange, String.class);
+        assertEquals("234", s);
+    }
+
+    @Test
+    public void testCeil() {
+        exchange.getMessage().setBody("5.3");
+
+        Expression expression = 
context.resolveLanguage("csimple").createExpression("${ceil()}");
+        int i = expression.evaluate(exchange, Integer.class);
+        assertEquals(6, i);
+
+        expression = 
context.resolveLanguage("csimple").createExpression("${ceil(${body})}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(6, i);
+
+        expression = 
context.resolveLanguage("csimple").createExpression("${ceil(6)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(6, i);
+
+        expression = 
context.resolveLanguage("csimple").createExpression("${ceil(6.0)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(6, i);
+
+        expression = 
context.resolveLanguage("csimple").createExpression("${ceil(6.1)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(7, i);
+
+        expression = 
context.resolveLanguage("csimple").createExpression("${ceil(-12.9)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(-12, i);
+
+        expression = 
context.resolveLanguage("csimple").createExpression("${ceil(0.0)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(0, i);
+
+        exchange.getMessage().setHeader("myNum", "234.56");
+        expression = 
context.resolveLanguage("csimple").createExpression("${ceil(${header.myNum})}");
+        String s = expression.evaluate(exchange, String.class);
+        assertEquals("235", s);
+    }
+
     @Override
     protected String getLanguageName() {
         return "csimple";
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 8c653a379aae..db79f38ceb37 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
@@ -97,15 +97,17 @@
     "list(val...)": { "index": 71, "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": 72, "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": "}" },
     "abs(exp)": { "index": 73, "kind": "function", "displayName": "Absolute 
Number", "group": "function", "label": "function", "required": false, 
"javaType": "Long", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the message body 
(or expression) to a long number and return the absolute value.", "ognl": 
false, "suffix": "}" },
-    "attachments": { "index": 74, "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": 75, "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": 76, "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": 77, "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": 78, "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": 79, "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": 80, "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": 81, "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": "}" },
-    "base64Encode(exp)": { "index": 82, "kind": "function", "displayName": 
"Base64 Encode", "group": "function", "label": "function", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Base64 encodes the 
message body (or expression)", "ognl": false, "suffix": "}" },
-    "base64Decode(exp)": { "index": 83, "kind": "function", "displayName": 
"Base64 Decode", "group": "function", "label": "function", "required": false, 
"javaType": "byte[]", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Base64 decodes the 
message body (or expression)", "ognl": false, "suffix": "}" }
+    "ceil(exp)": { "index": 74, "kind": "function", "displayName": "Ceil 
Number", "group": "function", "label": "function", "required": false, 
"javaType": "Integer", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Converts the message 
body (or expression) to a floating number and return the ceil value (rounded up 
to nearest integer).", "ognl": false, "suffix": "}" },
+    "floor(exp)": { "index": 75, "kind": "function", "displayName": "Floor 
Number", "group": "function", "label": "function", "required": false, 
"javaType": "Integer", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Converts the message 
body (or expression) to a floating number and return the floor value (rounded 
down to nearest integer).", "ognl": false, "suffix": "}" },
+    "attachments": { "index": 76, "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": 77, "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": 78, "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": 79, "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": 80, "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": 81, "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": 82, "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": 83, "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": "}" },
+    "base64Encode(exp)": { "index": 84, "kind": "function", "displayName": 
"Base64 Encode", "group": "function", "label": "function", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Base64 encodes the 
message body (or expression)", "ognl": false, "suffix": "}" },
+    "base64Decode(exp)": { "index": 85, "kind": "function", "displayName": 
"Base64 Decode", "group": "function", "label": "function", "required": false, 
"javaType": "byte[]", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Base64 decodes the 
message body (or expression)", "ognl": false, "suffix": "}" }
   }
 }
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 ac908913dc6a..76bb5f32c20b 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
@@ -126,6 +126,7 @@ NOTE: Some functions take 1 or more arguments enclosed in 
parentheses, and argum
 [width="100%",cols="10%,10%,80%",options="header",]
 |====
 |Function |Response Type |Description
+|`abs()` | `long` | Converts the message body to a long number and return the 
absolute value.
 |`abs(exp)` | `Long` | Converts the message body (or expression) to a long 
number and return the absolute value.
 |`bean(name.method)` | `Object` | Invoking a bean expression using the 
xref:components::bean-component.adoc[Bean] language. Specifying a method name, 
you must use dot as the separator. We also support the ?method=methodname 
syntax that is used by the xref:components::bean-component.adoc[Bean] 
component. Camel will by default lookup a bean by the given name. However, if 
you need to refer to a bean class (such as calling a static method), then you 
can prefix with the type, such as `bean:ty [...]
 |`body._OGNL_` | `Object` | The body invoked using a Camel _OGNL syntax_. For 
example to invoke the `getCountryCode` on the message body, you can use 
`${body.getCountryCode()}`. In the message body is a POJO then you can use a 
short-hand syntax `${body.countryCode}`.
@@ -138,6 +139,8 @@ NOTE: Some functions take 1 or more arguments enclosed in 
parentheses, and argum
 |`camelId` | `String` | The name of the Camel application (ie `CamelContext`).
 |`capitalize()` | `String` | Capitalizes the message body as a String value 
(upper case every words)
 |`capitalize(exp)` | `String` | Capitalizes the expression as a String value 
(upper case every words)
+|`ceil()` | `int` | Converts the message body to a floating number and return 
the ceil value (rounded up to nearest integer).
+|`ceil(exp)` | `int` | Converts the expression to a floating number and return 
the ceil value (rounded up to nearest integer).
 |`collate(size)` | `List` | 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/batch the split sub message into 
a group of N sub lists. This method works similar to the collate method in 
Groovy.
 |`concat(exp,exp,separator)` | `String` | Performs a string concat using two 
expressions (message body as default) with optional separator (uses comma by 
default).
 |`convertTo(type)` | `<T>` | Converts the message body to the specified type.
@@ -157,6 +160,8 @@ NOTE: Some functions take 1 or more arguments enclosed in 
parentheses, and argum
 |`exchangeProperty.key` | `Object` | Returns the value of the exchange 
property with the given key. Returns `null` if the property does not exists.
 |`exchangeProperty.key._OGNL_` | `Object` | Same as `exchangeProperty.key` and 
then invoke Camel _OGNL syntax_.
 |`exchange` | `Exchange` | The current `Exchange` object.
+|`floor()` | `int` | Converts the message body to a floating number and return 
the floor value (rounded down to nearest integer).
+|`floor(exp)` | `int` | Converts the expression to a floating number and 
return the floor value (rounded down to nearest integer).
 |`fromRouteId` | `String` | Returns the original route id where this 
`Exchange` was created.
 |`hash(exp,algorithm)` | `String` | Returns a hashed value (string in hex 
decimal) of the given expression. The algorithm can be `SHA-256` (default) or 
`SHA3-256`.
 |`header.key` | `Object` | The message header with the given key.
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 8247c789f591..eee1d36cce54 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
@@ -845,6 +845,34 @@ public final class CSimpleHelper {
         return body;
     }
 
+    public static Integer floor(Exchange exchange, Object value) {
+        Double body;
+        if (value != null) {
+            body = 
exchange.getContext().getTypeConverter().tryConvertTo(Double.class, exchange, 
value);
+        } else {
+            body = exchange.getMessage().getBody(Double.class);
+        }
+        if (body != null) {
+            double d = Math.floor(body);
+            return (int) d;
+        }
+        return null;
+    }
+
+    public static Integer ceil(Exchange exchange, Object value) {
+        Double body;
+        if (value != null) {
+            body = 
exchange.getContext().getTypeConverter().tryConvertTo(Double.class, exchange, 
value);
+        } else {
+            body = exchange.getMessage().getBody(Double.class);
+        }
+        if (body != null) {
+            double d = Math.ceil(body);
+            return (int) d;
+        }
+        return null;
+    }
+
     public static String trim(Exchange exchange, Object value) {
         String body;
         if (value != null) {
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 d8d760d5f564..3ea4c7497c3e 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,12 @@ public final class SimpleConstants {
     @Metadata(description = "Converts the message body (or expression) to a 
long number and return the absolute value.",
               label = "function", javaType = "Long", displayName = "Absolute 
Number")
     public static final String ABS = "abs(exp)";
+    @Metadata(description = "Converts the message body (or expression) to a 
floating number and return the ceil value (rounded up to nearest integer).",
+              label = "function", javaType = "Integer", displayName = "Ceil 
Number")
+    public static final String CEIL = "ceil(exp)";
+    @Metadata(description = "Converts the message body (or expression) to a 
floating number and return the floor value (rounded down to nearest integer).",
+              label = "function", javaType = "Integer", displayName = "Floor 
Number")
+    public static final String FLOOR = "floor(exp)";
     @Metadata(description = "All the attachments as a 
Map<String,DataHandler.", javaType = "java.util.Map", label = "function")
     public static final String ATTACHMENTS = "attachments";
     @Metadata(description = "The number of attachments. Is 0 if there are no 
attachments.", javaType = "int",
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 030024c92a3d..c82161a446fd 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
@@ -289,6 +289,90 @@ public final class SimpleExpressionBuilder {
         };
     }
 
+    /**
+     * Converts the given expressions to a floating number and return the 
floor value (uses message body if expression
+     * is null)
+     */
+    public static Expression floorExpression(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) {
+                Double value;
+                if (exp != null) {
+                    value = exp.evaluate(exchange, Double.class);
+                } else {
+                    value = exchange.getMessage().getBody(Double.class);
+                }
+                if (value != null) {
+                    double d = Math.floor(value);
+                    return (int) d;
+                }
+                return value;
+            }
+
+            @Override
+            public String toString() {
+                if (expression != null) {
+                    return "floor(" + expression + ")";
+                } else {
+                    return "floor()";
+                }
+            }
+        };
+    }
+
+    /**
+     * Converts the given expressions to a floating number and return the ceil 
value (uses message body if expression is
+     * null)
+     */
+    public static Expression ceilExpression(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) {
+                Double value;
+                if (exp != null) {
+                    value = exp.evaluate(exchange, Double.class);
+                } else {
+                    value = exchange.getMessage().getBody(Double.class);
+                }
+                if (value != null) {
+                    double d = Math.ceil(value);
+                    return (int) d;
+                }
+                return value;
+            }
+
+            @Override
+            public String toString() {
+                if (expression != null) {
+                    return "ceil(" + expression + ")";
+                } else {
+                    return "ceil()";
+                }
+            }
+        };
+    }
+
     /**
      * Trims 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 c3b153f1c0bf..803de1906676 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
@@ -1038,6 +1038,26 @@ public class SimpleFunctionExpression extends 
LiteralExpression {
             }
             return SimpleExpressionBuilder.absExpression(exp);
         }
+        // floor function
+        remainder = ifStartsWithReturnRemainder("floor(", function);
+        if (remainder != null) {
+            String exp = null;
+            String value = StringHelper.beforeLast(remainder, ")");
+            if (ObjectHelper.isNotEmpty(value)) {
+                exp = StringHelper.removeQuotes(value);
+            }
+            return SimpleExpressionBuilder.floorExpression(exp);
+        }
+        // ceil function
+        remainder = ifStartsWithReturnRemainder("ceil(", function);
+        if (remainder != null) {
+            String exp = null;
+            String value = StringHelper.beforeLast(remainder, ")");
+            if (ObjectHelper.isNotEmpty(value)) {
+                exp = StringHelper.removeQuotes(value);
+            }
+            return SimpleExpressionBuilder.ceilExpression(exp);
+        }
 
         // trim function
         remainder = ifStartsWithReturnRemainder("trim(", function);
@@ -2565,6 +2585,52 @@ public class SimpleFunctionExpression extends 
LiteralExpression {
             }
             return "Object o = " + exp + ";\n        return abs(exchange, o);";
         }
+        remainder = ifStartsWithReturnRemainder("floor(", 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: ${floor(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 floor(exchange, 
o);";
+        }
+        remainder = ifStartsWithReturnRemainder("ceil(", 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: ${ceil(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 ceil(exchange, 
o);";
+        }
 
         // trim function
         remainder = ifStartsWithReturnRemainder("trim(", 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 a53049877c1b..a93d87c2583d 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
@@ -2995,6 +2995,82 @@ public class SimpleTest extends LanguageTestSupport {
         assertEquals("222", s);
     }
 
+    @Test
+    public void testFloor() {
+        exchange.getMessage().setBody("5.3");
+
+        Expression expression = 
context.resolveLanguage("simple").createExpression("${floor()}");
+        int i = expression.evaluate(exchange, Integer.class);
+        assertEquals(5, i);
+
+        expression = 
context.resolveLanguage("simple").createExpression("${floor(${body})}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(5, i);
+
+        expression = 
context.resolveLanguage("simple").createExpression("${floor(6)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(6, i);
+
+        expression = 
context.resolveLanguage("simple").createExpression("${floor(6.0)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(6, i);
+
+        expression = 
context.resolveLanguage("simple").createExpression("${floor(6.8)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(6, i);
+
+        expression = 
context.resolveLanguage("simple").createExpression("${floor(-12.9)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(-13, i);
+
+        expression = 
context.resolveLanguage("simple").createExpression("${floor(0.0)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(0, i);
+
+        exchange.getMessage().setHeader("myNum", "234.56");
+        expression = 
context.resolveLanguage("simple").createExpression("${floor(${header.myNum})}");
+        String s = expression.evaluate(exchange, String.class);
+        assertEquals("234", s);
+    }
+
+    @Test
+    public void testCeil() {
+        exchange.getMessage().setBody("5.3");
+
+        Expression expression = 
context.resolveLanguage("simple").createExpression("${ceil()}");
+        int i = expression.evaluate(exchange, Integer.class);
+        assertEquals(6, i);
+
+        expression = 
context.resolveLanguage("simple").createExpression("${ceil(${body})}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(6, i);
+
+        expression = 
context.resolveLanguage("simple").createExpression("${ceil(6)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(6, i);
+
+        expression = 
context.resolveLanguage("simple").createExpression("${ceil(6.0)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(6, i);
+
+        expression = 
context.resolveLanguage("simple").createExpression("${ceil(6.1)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(7, i);
+
+        expression = 
context.resolveLanguage("simple").createExpression("${ceil(-12.9)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(-12, i);
+
+        expression = 
context.resolveLanguage("simple").createExpression("${ceil(0.0)}");
+        i = expression.evaluate(exchange, Integer.class);
+        assertEquals(0, i);
+
+        exchange.getMessage().setHeader("myNum", "234.56");
+        expression = 
context.resolveLanguage("simple").createExpression("${ceil(${header.myNum})}");
+        String s = expression.evaluate(exchange, String.class);
+        assertEquals("235", s);
+    }
+
     @Override
     protected String getLanguageName() {
         return "simple";


Reply via email to