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 236db5026993 camel-core - Add kindOfType function to simple
236db5026993 is described below

commit 236db50269933ba8af348301cf7e22962b12a63a
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Jan 26 21:46:48 2026 +0100

    camel-core - Add kindOfType function to simple
---
 .../org/apache/camel/catalog/languages/simple.json | 13 +++--
 .../language/csimple/joor/OriginalSimpleTest.java  | 66 ++++++++++++++++++++++
 .../org/apache/camel/language/simple/simple.json   | 13 +++--
 .../modules/languages/pages/simple-language.adoc   |  1 +
 .../camel/language/csimple/CSimpleHelper.java      | 18 ++++++
 .../camel/language/simple/SimpleConstants.java     |  4 ++
 .../language/simple/SimpleExpressionBuilder.java   | 52 +++++++++++++++++
 .../simple/ast/SimpleFunctionExpression.java       | 36 ++++++++++++
 .../apache/camel/language/simple/SimpleTest.java   | 66 ++++++++++++++++++++++
 9 files changed, 257 insertions(+), 12 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 59abdb4e780e..3e090fc27896 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
@@ -120,11 +120,12 @@
     "throwException(type,msg)": { "index": 93, "kind": "function", 
"displayName": "Throw Exception", "group": "function", "label": "function", 
"required": false, "javaType": "java.lang.Exception", "prefix": "${", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Deliberately throws an error. Uses 
IllegalArgumentException by default if no type is specified (use fully 
qualified classname).", "ognl": false, "suffix": "}" },
     "trim(exp)": { "index": 94, "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": "}" },
     "type:name.field": { "index": 95, "kind": "function", "displayName": "Java 
Field Value", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "To refer to a type or 
field by its classname. To refer to a field, you can append .FIELD_NAME. For 
example, you can refer to the constant field from Exchange as: 
`org.apache.camel.Exchange.FILE_NAME`", " [...]
-    "uppercase(exp)": { "index": 96, "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": "}" },
-    "uuid(type)": { "index": 97, "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 [...]
-    "variable.name": { "index": 98, "kind": "function", "displayName": 
"Variable", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "The variable with the 
given name", "ognl": true, "suffix": "}" },
-    "variableAs(key,type)": { "index": 99, "kind": "function", "displayName": 
"Variable As", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Converts the variable 
to the given type (classname).", "ognl": false, "suffix": "}" },
-    "variables": { "index": 100, "kind": "function", "displayName": 
"Variables", "group": "function", "label": "function", "required": false, 
"javaType": "java.util.Map", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns all the variables from the current Exchange in a Map", "ognl": false, 
"suffix": "}" },
-    "xpath(input,exp)": { "index": 101, "kind": "function", "displayName": 
"XPath", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "When working with XML 
data, then this allows using the XPath language, for example, to extract data 
from the message body (in XML format). This requires having camel-xpath JAR on 
the classpath. For input (optiona [...]
+    "kindOfType(exp)": { "index": 96, "kind": "function", "displayName": "Kind 
of Type", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "What kind of type is 
the value (null,number,string,boolean,array,object)", "ognl": false, "suffix": 
"}" },
+    "uppercase(exp)": { "index": 97, "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": "}" },
+    "uuid(type)": { "index": 98, "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 [...]
+    "variable.name": { "index": 99, "kind": "function", "displayName": 
"Variable", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "The variable with the 
given name", "ognl": true, "suffix": "}" },
+    "variableAs(key,type)": { "index": 100, "kind": "function", "displayName": 
"Variable As", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Converts the variable 
to the given type (classname).", "ognl": false, "suffix": "}" },
+    "variables": { "index": 101, "kind": "function", "displayName": 
"Variables", "group": "function", "label": "function", "required": false, 
"javaType": "java.util.Map", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns all the variables from the current Exchange in a Map", "ognl": false, 
"suffix": "}" },
+    "xpath(input,exp)": { "index": 102, "kind": "function", "displayName": 
"XPath", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "When working with XML 
data, then this allows using the XPath language, for example, to extract data 
from the message body (in XML format). This requires having camel-xpath JAR on 
the classpath. For input (optiona [...]
   }
 }
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 2d0eeed4ab73..d34e89ebdba8 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
@@ -53,6 +53,7 @@ import org.apache.camel.spi.Language;
 import org.apache.camel.spi.UuidGenerator;
 import org.apache.camel.spi.VariableRepository;
 import org.apache.camel.spi.VariableRepositoryFactory;
+import org.apache.camel.support.DefaultUuidGenerator;
 import org.apache.camel.support.ExchangeHelper;
 import org.apache.camel.support.LanguageHelper;
 import org.apache.camel.test.junit5.LanguageTestSupport;
@@ -3248,6 +3249,71 @@ public class OriginalSimpleTest extends 
LanguageTestSupport {
         assertEquals("Carlsberg is a beer", s);
     }
 
+    @Test
+    public void testKindOfType() {
+        exchange.getMessage().setBody(null);
+        Expression expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType()}");
+        String s = expression.evaluate(exchange, String.class);
+        assertEquals("null", s);
+
+        exchange.getMessage().setBody("Hello");
+        expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType()}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("string", s);
+        expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType(${body})}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("string", s);
+
+        exchange.getMessage().setBody(123);
+        expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType()}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("number", s);
+        expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType(${body})}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("number", s);
+
+        exchange.getMessage().setBody(98.76d);
+        expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType()}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("number", s);
+        expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType(${body})}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("number", s);
+
+        exchange.getMessage().setBody(true);
+        expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType()}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("boolean", s);
+        expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType(${body})}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("boolean", s);
+        exchange.getMessage().setBody("Hello");
+
+        exchange.getMessage().setBody(List.of("A", "B"));
+        expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType()}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("array", s);
+        expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType(${body})}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("array", s);
+
+        exchange.getMessage().setBody("abc".getBytes());
+        expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType()}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("array", s);
+        expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType(${body})}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("array", s);
+
+        exchange.getMessage().setBody(new DefaultUuidGenerator());
+        expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType()}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("object", s);
+        expression = 
context.resolveLanguage("csimple").createExpression("${kindOfType(${body})}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("object", 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 59abdb4e780e..3e090fc27896 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
@@ -120,11 +120,12 @@
     "throwException(type,msg)": { "index": 93, "kind": "function", 
"displayName": "Throw Exception", "group": "function", "label": "function", 
"required": false, "javaType": "java.lang.Exception", "prefix": "${", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Deliberately throws an error. Uses 
IllegalArgumentException by default if no type is specified (use fully 
qualified classname).", "ognl": false, "suffix": "}" },
     "trim(exp)": { "index": 94, "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": "}" },
     "type:name.field": { "index": 95, "kind": "function", "displayName": "Java 
Field Value", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "To refer to a type or 
field by its classname. To refer to a field, you can append .FIELD_NAME. For 
example, you can refer to the constant field from Exchange as: 
`org.apache.camel.Exchange.FILE_NAME`", " [...]
-    "uppercase(exp)": { "index": 96, "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": "}" },
-    "uuid(type)": { "index": 97, "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 [...]
-    "variable.name": { "index": 98, "kind": "function", "displayName": 
"Variable", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "The variable with the 
given name", "ognl": true, "suffix": "}" },
-    "variableAs(key,type)": { "index": 99, "kind": "function", "displayName": 
"Variable As", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Converts the variable 
to the given type (classname).", "ognl": false, "suffix": "}" },
-    "variables": { "index": 100, "kind": "function", "displayName": 
"Variables", "group": "function", "label": "function", "required": false, 
"javaType": "java.util.Map", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns all the variables from the current Exchange in a Map", "ognl": false, 
"suffix": "}" },
-    "xpath(input,exp)": { "index": 101, "kind": "function", "displayName": 
"XPath", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "When working with XML 
data, then this allows using the XPath language, for example, to extract data 
from the message body (in XML format). This requires having camel-xpath JAR on 
the classpath. For input (optiona [...]
+    "kindOfType(exp)": { "index": 96, "kind": "function", "displayName": "Kind 
of Type", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "What kind of type is 
the value (null,number,string,boolean,array,object)", "ognl": false, "suffix": 
"}" },
+    "uppercase(exp)": { "index": 97, "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": "}" },
+    "uuid(type)": { "index": 98, "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 [...]
+    "variable.name": { "index": 99, "kind": "function", "displayName": 
"Variable", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "The variable with the 
given name", "ognl": true, "suffix": "}" },
+    "variableAs(key,type)": { "index": 100, "kind": "function", "displayName": 
"Variable As", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Converts the variable 
to the given type (classname).", "ognl": false, "suffix": "}" },
+    "variables": { "index": 101, "kind": "function", "displayName": 
"Variables", "group": "function", "label": "function", "required": false, 
"javaType": "java.util.Map", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Returns all the variables from the current Exchange in a Map", "ognl": false, 
"suffix": "}" },
+    "xpath(input,exp)": { "index": 102, "kind": "function", "displayName": 
"XPath", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "When working with XML 
data, then this allows using the XPath language, for example, to extract data 
from the message body (in XML format). This requires having camel-xpath JAR on 
the classpath. For input (optiona [...]
   }
 }
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 7a005308126f..dbc55418d058 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
@@ -160,6 +160,7 @@ NOTE: Some functions take 1 or more arguments enclosed in 
parentheses, and argum
 |`headers[key]` | `Object` | *Deprecated* The message header with the given 
key.
 |`headers` | `Map` | All the message headers as a `java.util.Map`.
 |`id` | `String` | The message id
+|`kindOfType(exp)` | `String` | What kind of type is the value 
(null,number,string,boolean,array,object).
 |`logExchange` | `String` | Dumps the exchange for logging purpose (uses 
`ExchangeFormatter` to format the output).
 |`mandatoryBodyAs(type)` | `<T>` | Converts the message body to the given type 
determined by its classname. If the body is `null` then an exception is thrown.
 |`mandatoryBodyAs(type)._OGNL_` | `Object` | Same as `mandatoryBodyAs(type)` 
and then invoke Camel _OGNL syntax_.
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 9c2351e0a3d2..e321b9a272c6 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
@@ -1284,4 +1284,22 @@ public final class CSimpleHelper {
         return body;
     }
 
+    public static String kindOfType(Exchange exchange, Object value) {
+        if (value != null) {
+            Class<?> type = value.getClass();
+            if (ObjectHelper.isNumericType(type)) {
+                return "number";
+            } else if (boolean.class == type || Boolean.class == type) {
+                return "boolean";
+            } else if (value instanceof CharSequence) {
+                return "string";
+            } else if (ObjectHelper.isPrimitiveArrayType(type) || value 
instanceof Collection || value instanceof Map<?, ?>) {
+                return "array";
+            } else {
+                return "object";
+            }
+        }
+        return "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 464c49ba8ae5..a4df306f3fbc 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
@@ -389,6 +389,10 @@ public final class SimpleConstants {
               label = "function", javaType = "Object", displayName = "Java 
Field Value")
     public static final String TYPE = "type:name.field";
 
+    @Metadata(description = "What kind of type is the value 
(null,number,string,boolean,array,object)",
+              label = "function", javaType = "Object", displayName = "Kind of 
Type")
+    public static final String KIND_OF_TYPE = "kindOfType(exp)";
+
     @Metadata(description = "Uppercases the message body (or expression)", 
label = "function", javaType = "String",
               displayName = "Uppercase")
     public static final String UPPERCASE = "uppercase(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 479a99d6c08d..17ff20cdf974 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
@@ -589,6 +589,58 @@ public final class SimpleExpressionBuilder {
         };
     }
 
+    /**
+     * What kind of type is the expression
+     */
+    public static Expression kindOfTypeExpression(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) {
+                Object value;
+                if (exp != null) {
+                    value = exp.evaluate(exchange, Object.class);
+                } else {
+                    value = exchange.getMessage().getBody();
+                }
+                if (value != null) {
+                    Class<?> type = value.getClass();
+                    if (ObjectHelper.isNumericType(type)) {
+                        return "number";
+                    } else if (boolean.class == type || Boolean.class == type) 
{
+                        return "boolean";
+                    } else if (value instanceof CharSequence) {
+                        return "string";
+                    } else if (ObjectHelper.isPrimitiveArrayType(type) || 
value instanceof Collection
+                            || value instanceof Map<?, ?>) {
+                        return "array";
+                    } else {
+                        return "object";
+                    }
+                }
+                return "null";
+            }
+
+            @Override
+            public String toString() {
+                if (expression != null) {
+                    return "kindOfType(" + expression + ")";
+                } else {
+                    return "kindOfType()";
+                }
+            }
+        };
+    }
+
     /**
      * 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 8f518199c4a5..f0e4f91dd344 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
@@ -1143,6 +1143,17 @@ public class SimpleFunctionExpression extends 
LiteralExpression {
             return SimpleExpressionBuilder.isNotPredicate(exp);
         }
 
+        // whichKind function
+        remainder = ifStartsWithReturnRemainder("kindOfType(", function);
+        if (remainder != null) {
+            String exp = null;
+            String value = StringHelper.beforeLast(remainder, ")");
+            if (ObjectHelper.isNotEmpty(value)) {
+                exp = StringHelper.removeQuotes(value);
+            }
+            return SimpleExpressionBuilder.kindOfTypeExpression(exp);
+        }
+
         // trim function
         remainder = ifStartsWithReturnRemainder("trim(", function);
         if (remainder != null) {
@@ -2843,6 +2854,31 @@ public class SimpleFunctionExpression extends 
LiteralExpression {
                    + ";\n        return pad(exchange, value, width, 
separator);";
         }
 
+        // kindOfType function
+        remainder = ifStartsWithReturnRemainder("kindOfType(", 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: ${kindOfType(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 = "body";
+            }
+            return "Object o = " + exp + ";\n        return 
kindOfType(exchange, o);";
+        }
+
         // trim function
         remainder = ifStartsWithReturnRemainder("trim(", 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 4b86fad76f42..d646da09c351 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
@@ -54,6 +54,7 @@ import org.apache.camel.spi.Registry;
 import org.apache.camel.spi.UuidGenerator;
 import org.apache.camel.spi.VariableRepository;
 import org.apache.camel.spi.VariableRepositoryFactory;
+import org.apache.camel.support.DefaultUuidGenerator;
 import org.apache.camel.support.ExchangeHelper;
 import org.apache.camel.support.LanguageHelper;
 import org.apache.camel.util.InetAddressUtil;
@@ -3695,6 +3696,71 @@ public class SimpleTest extends LanguageTestSupport {
         assertEquals("Carlsberg is a beer", s);
     }
 
+    @Test
+    public void testKindOfType() {
+        exchange.getMessage().setBody(null);
+        Expression expression = 
context.resolveLanguage("simple").createExpression("${kindOfType()}");
+        String s = expression.evaluate(exchange, String.class);
+        assertEquals("null", s);
+
+        exchange.getMessage().setBody("Hello");
+        expression = 
context.resolveLanguage("simple").createExpression("${kindOfType()}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("string", s);
+        expression = 
context.resolveLanguage("simple").createExpression("${kindOfType(${body})}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("string", s);
+
+        exchange.getMessage().setBody(123);
+        expression = 
context.resolveLanguage("simple").createExpression("${kindOfType()}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("number", s);
+        expression = 
context.resolveLanguage("simple").createExpression("${kindOfType(${body})}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("number", s);
+
+        exchange.getMessage().setBody(98.76d);
+        expression = 
context.resolveLanguage("simple").createExpression("${kindOfType()}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("number", s);
+        expression = 
context.resolveLanguage("simple").createExpression("${kindOfType(${body})}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("number", s);
+
+        exchange.getMessage().setBody(true);
+        expression = 
context.resolveLanguage("simple").createExpression("${kindOfType()}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("boolean", s);
+        expression = 
context.resolveLanguage("simple").createExpression("${kindOfType(${body})}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("boolean", s);
+        exchange.getMessage().setBody("Hello");
+
+        exchange.getMessage().setBody(List.of("A", "B"));
+        expression = 
context.resolveLanguage("simple").createExpression("${kindOfType()}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("array", s);
+        expression = 
context.resolveLanguage("simple").createExpression("${kindOfType(${body})}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("array", s);
+
+        exchange.getMessage().setBody("abc".getBytes());
+        expression = 
context.resolveLanguage("simple").createExpression("${kindOfType()}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("array", s);
+        expression = 
context.resolveLanguage("simple").createExpression("${kindOfType(${body})}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("array", s);
+
+        exchange.getMessage().setBody(new DefaultUuidGenerator());
+        expression = 
context.resolveLanguage("simple").createExpression("${kindOfType()}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("object", s);
+        expression = 
context.resolveLanguage("simple").createExpression("${kindOfType(${body})}");
+        s = expression.evaluate(exchange, String.class);
+        assertEquals("object", s);
+    }
+
     @Override
     protected String getLanguageName() {
         return "simple";

Reply via email to