This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch lan-markup
in repository https://gitbox.apache.org/repos/asf/camel.git

commit f0a372de9ea0cf875d353e52f9098814bae03a93
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Fri Aug 16 10:02:12 2024 +0200

    CAMEL-20569: camel-catalog - Markup languages which functions they support 
for better doc and tooling.
---
 .../org/apache/camel/language/simple/simple.json   | 58 ++++++++++++-------
 .../camel/language/simple/SimpleConstants.java     | 67 ++++++++++++++++++++++
 .../org/apache/camel/tooling/model/JsonMapper.java | 19 +++++-
 .../apache/camel/tooling/model/LanguageModel.java  | 28 +++++++++
 .../org/apache/camel/tooling/util/Strings.java     | 16 ++++++
 .../camel/maven/packaging/PackageLanguageMojo.java | 11 ++++
 6 files changed, 178 insertions(+), 21 deletions(-)

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 09b0ba79cb7..4054c67f8b8 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
@@ -22,25 +22,43 @@
     "trim": { "index": 3, "kind": "attribute", "displayName": "Trim", "group": 
"advanced", "label": "advanced", "required": false, "type": "boolean", 
"javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": true, "description": "Whether to trim the 
value to remove leading and trailing whitespaces and line breaks" }
   },
   "functions": {
-    "body": { "index": 0, "kind": "function", "displayName": "Body", "group": 
"function", "label": "function", "required": false, "javaType": "Object", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The message body" },
-    "prettyBody": { "index": 1, "kind": "function", "displayName": "Pretty 
Body", "group": "function", "label": "function", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Converts the body to a String, and attempts to 
pretty print if JSon or XML; otherwise the body is returned as the String 
value." },
-    "bodyOneLine": { "index": 2, "kind": "function", "displayName": "Body One 
Line", "group": "function", "label": "function", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Converts the body to a String and removes all 
line-breaks, so the string is in one line." },
-    "originalBody": { "index": 3, "kind": "function", "displayName": "Original 
Body", "group": "function", "label": "function", "required": false, "javaType": 
"Object", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The original incoming body (only available if 
allowUseOriginalMessage=true)." },
-    "id": { "index": 4, "kind": "function", "displayName": "Id", "group": 
"function", "label": "function", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The message id" },
-    "messageTimestamp": { "index": 5, "kind": "function", "displayName": 
"Message Timestamp", "group": "function", "label": "function", "required": 
false, "javaType": "long", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The message timestamp 
(millis since epoc) that this message originates from. Some systems like JMS, 
Kafka, AWS have a timestamp on the event\/message that Camel received. This 
method returns the timestamp if a timestamp  [...]
-    "exchangeId": { "index": 6, "kind": "function", "displayName": "Exchange 
Id", "group": "function", "label": "function", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The exchange id" },
-    "exchange": { "index": 7, "kind": "function", "displayName": "Exchange", 
"group": "function", "label": "function", "required": false, "javaType": 
"org.apache.camel.Exchange", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The exchange" },
-    "exception": { "index": 8, "kind": "function", "displayName": "Exception", 
"group": "function", "label": "function", "required": false, "javaType": 
"java.lang.Exception", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The exception object on the exchange 
(also from caught exceptions), is null if no exception present." },
-    "exception.message": { "index": 9, "kind": "function", "displayName": 
"Exception.message", "group": "function", "label": "function", "required": 
false, "javaType": "String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The exception message 
(also from caught exceptions), is null if no exception present." },
-    "exception.stackTrace": { "index": 10, "kind": "function", "displayName": 
"Exception.stack Trace", "group": "function", "label": "function", "required": 
false, "javaType": "String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The exception stacktrace 
(also from caught exceptions), is null if no exception present." },
-    "threadId": { "index": 11, "kind": "function", "displayName": "Thread Id", 
"group": "function", "label": "function", "required": false, "javaType": 
"long", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Returns the id of the current thread. Can be 
used for logging." },
-    "threadName": { "index": 12, "kind": "function", "displayName": "Thread 
Name", "group": "function", "label": "function", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Returns the name of the current thread. Can be 
used for logging." },
-    "hostName": { "index": 13, "kind": "function", "displayName": "Host Name", 
"group": "function", "label": "function", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Returns the local hostname (may be empty if 
not possible to resolve)." },
-    "camelId": { "index": 14, "kind": "function", "displayName": "Camel Id", 
"group": "function", "label": "function", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The name of the CamelContext" },
-    "routeId": { "index": 15, "kind": "function", "displayName": "Route Id", 
"group": "function", "label": "function", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The route id of the current route the Exchange 
is being routed" },
-    "fromRouteId": { "index": 16, "kind": "function", "displayName": "From 
Route Id", "group": "function", "label": "function", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The original route id where this 
exchange was created." },
-    "routeGroup": { "index": 17, "kind": "function", "displayName": "Route 
Group", "group": "function", "label": "function", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Returns the route group of the current 
route the Exchange is being routed. Not all routes have a group assigned, so 
this may be null." },
-    "stepId": { "index": 18, "kind": "function", "displayName": "Step Id", 
"group": "function", "label": "function", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Returns the id of the current step the 
Exchange is being routed." },
-    "null": { "index": 19, "kind": "function", "displayName": "Null", "group": 
"function", "label": "function", "required": false, "javaType": "Object", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Represents a null value" }
+    "body": { "index": 0, "kind": "function", "displayName": "Body", "group": 
"function", "label": "function", "required": false, "javaType": "Object", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The message body", "suffix": "}" },
+    "prettyBody": { "index": 1, "kind": "function", "displayName": "Pretty 
Body", "group": "function", "label": "function", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the body to a 
String, and attempts to pretty print if JSon or XML; otherwise the body is 
returned as the String value.", "suffix": "}" },
+    "bodyOneLine": { "index": 2, "kind": "function", "displayName": "Body One 
Line", "group": "function", "label": "function", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Converts the body to a 
String and removes all line-breaks, so the string is in one line.", "suffix": 
"}" },
+    "originalBody": { "index": 3, "kind": "function", "displayName": "Original 
Body", "group": "function", "label": "function", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The original incoming body 
(only available if allowUseOriginalMessage=true).", "suffix": "}" },
+    "id": { "index": 4, "kind": "function", "displayName": "Id", "group": 
"function", "label": "function", "required": false, "javaType": "String", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The message id", "suffix": "}" },
+    "messageTimestamp": { "index": 5, "kind": "function", "displayName": 
"Message Timestamp", "group": "function", "label": "function", "required": 
false, "javaType": "long", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
message timestamp (millis since epoc) that this message originates from. Some 
systems like JMS, Kafka, AWS have a timestamp on the event\/message that Camel 
received. This method returns the timestamp [...]
+    "exchangeId": { "index": 6, "kind": "function", "displayName": "Exchange 
Id", "group": "function", "label": "function", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The exchange id", 
"suffix": "}" },
+    "exchange": { "index": 7, "kind": "function", "displayName": "Exchange", 
"group": "function", "label": "function", "required": false, "javaType": 
"org.apache.camel.Exchange", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
exchange", "suffix": "}" },
+    "exception": { "index": 8, "kind": "function", "displayName": "Exception", 
"group": "function", "label": "function", "required": false, "javaType": 
"java.lang.Exception", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "The exception object 
on the exchange (also from caught exceptions), is null if no exception 
present.", "suffix": "}" },
+    "exception.message": { "index": 9, "kind": "function", "displayName": 
"Exception.message", "group": "function", "label": "function", "required": 
false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
exception message (also from caught exceptions), is null if no exception 
present.", "suffix": "}" },
+    "exception.stackTrace": { "index": 10, "kind": "function", "displayName": 
"Exception.stack Trace", "group": "function", "label": "function", "required": 
false, "javaType": "String", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
exception stacktrace (also from caught exceptions), is null if no exception 
present.", "suffix": "}" },
+    "threadId": { "index": 11, "kind": "function", "displayName": "Thread Id", 
"group": "function", "label": "function", "required": false, "javaType": 
"long", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the id of the 
current thread. Can be used for logging.", "suffix": "}" },
+    "threadName": { "index": 12, "kind": "function", "displayName": "Thread 
Name", "group": "function", "label": "function", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the name of the 
current thread. Can be used for logging.", "suffix": "}" },
+    "hostName": { "index": 13, "kind": "function", "displayName": "Host Name", 
"group": "function", "label": "function", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the local hostname 
(may be empty if not possible to resolve).", "suffix": "}" },
+    "camelId": { "index": 14, "kind": "function", "displayName": "Camel Id", 
"group": "function", "label": "function", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The name of the 
CamelContext", "suffix": "}" },
+    "routeId": { "index": 15, "kind": "function", "displayName": "Route Id", 
"group": "function", "label": "function", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The route id of the 
current route the Exchange is being routed", "suffix": "}" },
+    "fromRouteId": { "index": 16, "kind": "function", "displayName": "From 
Route Id", "group": "function", "label": "function", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "The original route id 
where this exchange was created.", "suffix": "}" },
+    "routeGroup": { "index": 17, "kind": "function", "displayName": "Route 
Group", "group": "function", "label": "function", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Returns the route 
group of the current route the Exchange is being routed. Not all routes have a 
group assigned, so this may be null.", "suffix": "}" },
+    "stepId": { "index": 18, "kind": "function", "displayName": "Step Id", 
"group": "function", "label": "function", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns the id of the 
current step the Exchange is being routed.", "suffix": "}" },
+    "null": { "index": 19, "kind": "function", "displayName": "Null", "group": 
"function", "label": "function", "required": false, "javaType": "Object", 
"prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Represents a null value", "suffix": "}" },
+    "messageAs(type)": { "index": 20, "kind": "function", "displayName": 
"Message As(type)", "group": "function", "label": "function", "required": 
false, "javaType": "Object", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Converts the message to the given type (classname).", "suffix": "}" },
+    "bodyAs(type)": { "index": 21, "kind": "function", "displayName": "Body 
As(type)", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Converts the message 
body to the given type (classname).", "suffix": "}" },
+    "mandatoryBodyAs(type)": { "index": 22, "kind": "function", "displayName": 
"Mandatory Body As(type)", "group": "function", "label": "function", 
"required": false, "javaType": "Object", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Converts the message body to the given type (classname). If the body is null 
then the function will fail with an exception", "suffix": "}" },
+    "headerAs(key,type)": { "index": 23, "kind": "function", "displayName": 
"Header As(key,type)", "group": "function", "label": "function", "required": 
false, "javaType": "Object", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Converts the message header to the given type (classname).", "suffix": "}" },
+    "headers": { "index": 24, "kind": "function", "displayName": "Headers", 
"group": "function", "label": "function", "required": false, "javaType": 
"java.util.Map", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Returns all the message 
headers in a Map", "suffix": "}" },
+    "variableAs(key,type)": { "index": 25, "kind": "function", "displayName": 
"Variable As(key,type)", "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).", "suffix": "}" },
+    "variables": { "index": 26, "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", "suffix": "}" },
+    "jq(exp)": { "index": 27, "kind": "function", "displayName": "Jq(exp)", 
"group": "function", "label": "function", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "When working with JSon 
data, then this allows using the JQ language, for example, to extract data from 
the message body (in JSon format). This requires having camel-jq JAR on the 
classpath.", "suffix": "}" },
+    "jq(input,exp)": { "index": 28, "kind": "function", "displayName": 
"Jq(input,exp)", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "When working with JSon 
data, then this allows using the JQ language, for example, to extract data from 
the message body (in JSon format). This requires having camel-jq JAR on the 
classpath. For input, you can [...]
+    "jsonpath(exp)": { "index": 29, "kind": "function", "displayName": 
"Jsonpath(exp)", "group": "function", "label": "function", "required": false, 
"javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "When working with JSon 
data, then this allows using the JSonPath language, for example, to extract 
data from the message body (in JSon format). This requires having 
camel-jsonpath JAR on the classpath.", "suf [...]
+    "jsonpath(input,exp)": { "index": 30, "kind": "function", "displayName": 
"Jsonpath(input,exp)", "group": "function", "label": "function", "required": 
false, "javaType": "Object", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"When working with JSon data, then this allows using the JSonPath language, for 
example, to extract data from the message body (in JSon format). This requires 
having camel-jsonpath JAR on the class [...]
+    "xpath(exp)": { "index": 31, "kind": "function", "displayName": 
"Xpath(exp)", "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.", "suffix": "}" },
+    "xpath(input,exp)": { "index": 32, "kind": "function", "displayName": 
"Xpath(input,exp)", "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 inpu [...]
+    "sys.name": { "index": 33, "kind": "function", "displayName": "Sys.name", 
"group": "function", "label": "function", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The JVM system property 
with the given name", "suffix": "}" },
+    "env.name": { "index": 34, "kind": "function", "displayName": "Env.name", 
"group": "function", "label": "function", "required": false, "javaType": 
"Object", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The OS environment 
variable with the given name", "suffix": "}" },
+    "pretty(exp)": { "index": 35, "kind": "function", "displayName": 
"Pretty(exp)", "group": "function", "label": "function", "required": false, 
"javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "Converts the 
expression to a String, and attempts to pretty print if JSon or XML, otherwise 
the expression is returned as the String value.", "suffix": "}" },
+    "date(command)": { "index": 36, "kind": "function", "displayName": 
"Date(command)", "group": "function", "label": "function", "required": false, 
"javaType": "java.util.Date", "prefix": "${", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": 
"Evaluates to a java.util.Date object. Supported commands are: `now` for 
current timestamp, `exchangeCreated` for the timestamp when the current 
exchange was created, `header.xxx` to use the Long\/Date [...]
+    "date-with-timezone(command:timezone:pattern)": { "index": 37, "kind": 
"function", "displayName": "Date-with-timezone(command:timezone:pattern)", 
"group": "function", "label": "function", "required": false, "javaType": 
"String", "prefix": "${", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Formats the date to a 
String using the given date pattern, and with support for timezone. Supported 
commands are: `now` for current timestamp, `ex [...]
   }
 }
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 a4f2ce69140..3f0446c3358 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
@@ -18,6 +18,7 @@ package org.apache.camel.language.simple;
 
 import org.apache.camel.spi.Metadata;
 
+@Metadata(label = "function", annotations = { "prefix=${", "suffix=}" })
 public final class SimpleConstants {
 
     @Metadata(description = "The message body", javaType = "Object", label = 
"function")
@@ -78,5 +79,71 @@ public final class SimpleConstants {
     public static final String STEP_ID = "stepId";
     @Metadata(description = "Represents a null value", label = "function", 
javaType = "Object")
     public static final String NULL = "null";
+    @Metadata(description = "Converts the message to the given type 
(classname).", label = "function", javaType = "Object")
+    public static final String MESSAGE_AS = "messageAs(type)";
+    @Metadata(description = "Converts the message body to the given type 
(classname).", label = "function", javaType = "Object")
+    public static final String BODY_AS = "bodyAs(type)";
+    @Metadata(description = "Converts the message body to the given type 
(classname). If the body is null then the function will fail with an exception",
+              label = "function", javaType = "Object")
+    public static final String MANDATORY_BODY_AS = "mandatoryBodyAs(type)";
+    @Metadata(description = "Converts the message header to the given type 
(classname).", label = "function",
+              javaType = "Object")
+    public static final String HEADER_AS = "headerAs(key,type)";
+    @Metadata(description = "Returns all the message headers in a Map", label 
= "function", javaType = "java.util.Map")
+    public static final String HEADERS = "headers";
+    @Metadata(description = "Converts the variable to the given type 
(classname).", label = "function",
+              javaType = "Object")
+    public static final String VARIABLE_AS = "variableAs(key,type)";
+    @Metadata(description = "Returns all the variables from the current 
Exchange in a Map", label = "function",
+              javaType = "java.util.Map")
+    public static final String VARIABLES = "variables";
+    @Metadata(description = "When working with JSon data, then this allows 
using the JQ language, for example, to extract data from the message body (in 
JSon format). This requires having camel-jq JAR on the classpath.",
+              label = "function", javaType = "Object")
+    public static final String JQ = "jq(exp)";
+    @Metadata(description = "When working with JSon data, then this allows 
using the JQ language, for example, to extract data from the message body (in 
JSon format). This requires having camel-jq JAR on the classpath."
+                            + " For input, you can choose `header:key`, 
`exchangeProperty:key` or `variable:key` to use as input for the JSon payload 
instead of the message body.",
+              label = "function", javaType = "Object")
+    public static final String JQ_INPUT = "jq(input,exp)";
+    @Metadata(description = "When working with JSon data, then this allows 
using the JSonPath language, for example, to extract data from the message body 
(in JSon format). This requires having camel-jsonpath JAR on the classpath.",
+              label = "function", javaType = "Object")
+    public static final String JSONPATH = "jsonpath(exp)";
+    @Metadata(description = "When working with JSon data, then this allows 
using the JSonPath language, for example, to extract data from the message body 
(in JSon format). This requires having camel-jsonpath JAR on the classpath."
+                            + " For input, you can choose `header:key`, 
`exchangeProperty:key` or `variable:key` to use as input for the JSon payload 
instead of the message body.",
+              label = "function", javaType = "Object")
+    public static final String JSONPATH_INPUT = "jsonpath(input,exp)";
+    @Metadata(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.",
+              label = "function", javaType = "Object")
+    public static final String XPATH = "xpath(exp)";
+    @Metadata(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, you can choose `header:key`, 
`exchangeProperty:key` or `variable:key` to use as input for the XML payload 
instead of the message body.",
+              label = "function", javaType = "Object")
+    public static final String XPATH_INPUT = "xpath(input,exp)";
+    @Metadata(description = "The JVM system property with the given name", 
label = "function", javaType = "Object")
+    public static final String SYS = "sys.name";
+    @Metadata(description = "The OS environment variable with the given name", 
label = "function", javaType = "Object")
+    public static final String ENV = "env.name";
+    @Metadata(description = "Converts the expression to a String, and attempts 
to pretty print if JSon or XML, otherwise the expression is returned as the 
String value.",
+              label = "function", javaType = "String")
+    public static final String PRETTY = "pretty(exp)";
+    @Metadata(description = "Evaluates to a java.util.Date object."
+                            + " Supported commands are: `now` for current 
timestamp,"
+                            + " `exchangeCreated` for the timestamp when the 
current exchange was created,"
+                            + " `header.xxx` to use the Long/Date object in 
the header with the key xxx."
+                            + " `variable.xxx` to use the Long/Date in the 
variable with the key xxx."
+                            + " `exchangeProperty.xxx` to use the Long/Date 
object in the exchange property with the key xxx."
+                            + " `file` for the last modified timestamp of the 
file (available with a File consumer)."
+                            + " Command accepts offsets such as: `now-24h` or 
`header.xxx+1h` or even `now+1h30m-100`.",
+              label = "function", javaType = "java.util.Date")
+    public static final String DATE = "date(command)";
+    @Metadata(description = "Formats the date to a String using the given date 
pattern, and with support for timezone."
+                            + " Supported commands are: `now` for current 
timestamp,"
+                            + " `exchangeCreated` for the timestamp when the 
current exchange was created,"
+                            + " `header.xxx` to use the Long/Date object in 
the header with the key xxx."
+                            + " `variable.xxx` to use the Long/Date in the 
variable with the key xxx."
+                            + " `exchangeProperty.xxx` to use the Long/Date 
object in the exchange property with the key xxx."
+                            + " `file` for the last modified timestamp of the 
file (available with a File consumer)."
+                            + " Command accepts offsets such as: `now-24h` or 
`header.xxx+1h` or even `now+1h30m-100`.",
+              label = "function", javaType = "String")
+    public static final String DATE_WITH_TIMEZONE = 
"date-with-timezone(command:timezone:pattern)";
 
 }
diff --git 
a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java
 
b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java
index a923bbdf698..d01b4a3a4c4 100644
--- 
a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java
+++ 
b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java
@@ -415,7 +415,7 @@ public final class JsonMapper {
         wrapper.put("properties", asJsonObject(model.getOptions()));
         final List<LanguageModel.LanguageFunctionModel> functions = 
model.getFunctions();
         if (!functions.isEmpty()) {
-            wrapper.put("functions", asJsonObject(functions));
+            wrapper.put("functions", asJsonObjectFunctions(functions));
         }
         return wrapper;
     }
@@ -603,6 +603,23 @@ public final class JsonMapper {
         return json;
     }
 
+    public static JsonObject 
asJsonObjectFunctions(List<LanguageModel.LanguageFunctionModel> options) {
+        JsonObject json = new JsonObject();
+        for (int i = 0; i < options.size(); i++) {
+            var o = options.get(i);
+            o.setIndex(i);
+            JsonObject jo = asJsonObject(o);
+            if (o.getPrefix() != null) {
+                jo.put("prefix", o.getPrefix());
+            }
+            if (o.getSuffix() != null) {
+                jo.put("suffix", o.getSuffix());
+            }
+            json.put(o.getName(), jo);
+        }
+        return json;
+    }
+
     public static JsonObject apiModelAsJsonObject(Collection<ApiModel> model, 
boolean options) {
         JsonObject root = new JsonObject();
         model.forEach(a -> {
diff --git 
a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/LanguageModel.java
 
b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/LanguageModel.java
index f2284c8aa70..429ad3ea929 100644
--- 
a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/LanguageModel.java
+++ 
b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/LanguageModel.java
@@ -68,6 +68,16 @@ public class LanguageModel extends 
ArtifactModel<LanguageModel.LanguageOptionMod
          */
         private String constantName;
 
+        /**
+         * Optional prefix for the function
+         */
+        private String prefix;
+
+        /**
+         * Optional suffix for the function
+         */
+        private String suffix;
+
         public String getConstantName() {
             return constantName;
         }
@@ -75,6 +85,24 @@ public class LanguageModel extends 
ArtifactModel<LanguageModel.LanguageOptionMod
         public void setConstantName(String constantName) {
             this.constantName = constantName;
         }
+
+        @Override
+        public String getPrefix() {
+            return prefix;
+        }
+
+        @Override
+        public void setPrefix(String prefix) {
+            this.prefix = prefix;
+        }
+
+        public String getSuffix() {
+            return suffix;
+        }
+
+        public void setSuffix(String suffix) {
+            this.suffix = suffix;
+        }
     }
 
 }
diff --git 
a/tooling/camel-tooling-util/src/main/java/org/apache/camel/tooling/util/Strings.java
 
b/tooling/camel-tooling-util/src/main/java/org/apache/camel/tooling/util/Strings.java
index f6670e6be27..25dbb75006f 100644
--- 
a/tooling/camel-tooling-util/src/main/java/org/apache/camel/tooling/util/Strings.java
+++ 
b/tooling/camel-tooling-util/src/main/java/org/apache/camel/tooling/util/Strings.java
@@ -69,6 +69,22 @@ public final class Strings {
         return text.substring(index + after.length());
     }
 
+    /**
+     * Returns the string after the given token
+     *
+     * @param  text         the text
+     * @param  after        the token
+     * @param  defaultValue the default value
+     * @return              the text after the token, or default value if text 
does not contain the token
+     */
+    public static String after(String text, String after, String defaultValue) 
{
+        int index = text.indexOf(after);
+        if (index < 0) {
+            return defaultValue;
+        }
+        return text.substring(index + after.length());
+    }
+
     /**
      * Returns the canonical class name by removing any generic type 
information.
      */
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageLanguageMojo.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageLanguageMojo.java
index c9c561e5929..ab2c062d58b 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageLanguageMojo.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageLanguageMojo.java
@@ -295,10 +295,21 @@ public class PackageLanguageMojo extends 
AbstractGeneratorMojo {
 
     private void addFunction(LanguageModel model, Field field) throws 
Exception {
         final Class<?> declaringClass = field.getDeclaringClass();
+        final Metadata cm = declaringClass.getAnnotation(Metadata.class);
+        String prefix = null;
+        String suffix = null;
+        if (cm != null && cm.annotations() != null) {
+            for (String s : cm.annotations()) {
+                prefix = Strings.after(s, "prefix=", prefix);
+                suffix = Strings.after(s, "suffix=", suffix);
+            }
+        }
         final Metadata metadata = field.getAnnotation(Metadata.class);
         LanguageModel.LanguageFunctionModel fun = new 
LanguageModel.LanguageFunctionModel();
         fun.setConstantName(String.format("%s#%s", declaringClass.getName(), 
field.getName()));
         fun.setName((String) field.get(null));
+        fun.setPrefix(prefix);
+        fun.setSuffix(suffix);
         fun.setDescription(metadata.description().trim());
         fun.setKind("function");
         String displayName = metadata.displayName();


Reply via email to