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 f24bb4f884a CAMEL-20569: camel-catalog - Markup languages which functions they support for better doc and tooling. (#15177) f24bb4f884a is described below commit f24bb4f884a24d984a0d650e1befa96a5784ddc7 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Fri Aug 16 14:24:55 2024 +0200 CAMEL-20569: camel-catalog - Markup languages which functions they support for better doc and tooling. (#15177) CAMEL-20569: camel-catalog - Markup languages which functions they support for better doc and tooling. --- .../org/apache/camel/catalog/languages/file.json | 17 ++ .../org/apache/camel/catalog/languages/simple.json | 57 ++++++ .../org/apache/camel/spi/annotations/Language.java | 13 ++ .../org/apache/camel/language/simple/file.json | 17 ++ .../org/apache/camel/language/simple/simple.json | 57 ++++++ .../modules/languages/pages/file-language.adoc | 2 +- .../modules/languages/pages/simple-language.adoc | 6 +- .../camel/language/simple/FileConstants.java | 59 ++++++ .../apache/camel/language/simple/FileLanguage.java | 2 +- .../camel/language/simple/SimpleConstants.java | 215 +++++++++++++++++++++ .../camel/language/simple/SimpleLanguage.java | 2 +- .../camel/maven/dsl/yaml/support/Schema.java | 2 + .../org/apache/camel/tooling/model/JsonMapper.java | 22 +++ .../apache/camel/tooling/model/LanguageModel.java | 70 +++++++ .../org/apache/camel/tooling/util/Strings.java | 16 ++ .../packaging/AbstractGenerateConfigurerMojo.java | 10 + .../camel/maven/packaging/PackageLanguageMojo.java | 99 +++++++++- .../camel/maven/packaging/generics/ClassUtil.java | 4 +- .../org/apache/camel/spi/annotations/Language.java | 13 ++ 19 files changed, 673 insertions(+), 10 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/file.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/file.json index 83d94c000d3..16ae6217ad2 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/file.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/file.json @@ -20,5 +20,22 @@ "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax" }, "resultType": { "index": 2, "kind": "attribute", "displayName": "Result Type", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the class of the result type (type from output)" }, "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": { + "file:name": { "index": 0, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file name (relative from starting directory)", "ognl": false, "suffix": "}" }, + "file:name.noext": { "index": 1, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file name (relative from starting directory) without extension", "ognl": false, "suffix": "}" }, + "file:name.noext.single": { "index": 2, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file name (relative from starting directory) without extension. If the file name has multiple dots, then this expression strips and only returns the last part.", "ognl": false, "suffix": "}" }, + "file:name.ext": { "index": 3, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file extension", "ognl": false, "suffix": "}" }, + "file:name.ext.single": { "index": 4, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file extension. If the file extension has multiple dots, then this expression strips and only returns the last part.", "ognl": false, "suffix": "}" }, + "file:onlyname": { "index": 5, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "\u2020he file name (without any leading paths)", "ognl": false, "suffix": "}" }, + "file:onlyname.noext": { "index": 6, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "\u2020he file name (without any leading paths) without extension", "ognl": false, "suffix": "}" }, + "file:onlyname.noext.single": { "index": 7, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "\u2020he file name (without any leading paths) without extension. If the file name has multiple dots, then this expression strips and only returns the last part.", "ognl": false, "suffix": "}" }, + "file:parent": { "index": 8, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file parent directory (null if no parent directory)", "ognl": false, "suffix": "}" }, + "file:path": { "index": 9, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file path", "ognl": false, "suffix": "}" }, + "file:absolute": { "index": 10, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "boolean", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Whether the file is regarded as absolute or relative", "ognl": false, "suffix": "}" }, + "file:absolute.path": { "index": 11, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The absolute file path", "ognl": false, "suffix": "}" }, + "file:length": { "index": 12, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the file", "ognl": false, "suffix": "}" }, + "file:size": { "index": 13, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the file", "ognl": false, "suffix": "}" }, + "file:modified": { "index": 14, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file modification date", "ognl": false, "suffix": "}" } } } 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 223741d6576..2fa67ebaf9d 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 @@ -20,5 +20,62 @@ "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax" }, "resultType": { "index": 2, "kind": "attribute", "displayName": "Result Type", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the class of the result type (type from output)" }, "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", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message body", "ognl": true, "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.", "ognl": false, "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.", "ognl": false, "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).", "ognl": false, "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", "ognl": false, "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", "ognl": false, "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 current exchange", "ognl": true, "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.", "ognl": true, "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.", "ognl": false, "suffix": "}" }, + "exception.stackTrace": { "index": 10, "kind": "function", "displayName": "Exception Stacktrace", "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.", "ognl": false, "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.", "ognl": false, "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.", "ognl": false, "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).", "ognl": false, "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", "ognl": false, "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", "ognl": false, "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.", "ognl": false, "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.", "ognl": false, "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.", "ognl": false, "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", "ognl": false, "suffix": "}" }, + "messageAs(type)": { "index": 20, "kind": "function", "displayName": "Message As", "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).", "ognl": true, "suffix": "}" }, + "bodyAs(type)": { "index": 21, "kind": "function", "displayName": "Body As", "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).", "ognl": true, "suffix": "}" }, + "mandatoryBodyAs(type)": { "index": 22, "kind": "function", "displayName": "Mandatory Body As", "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", "ognl": true, "suffix": "}" }, + "headerAs(key,type)": { "index": 23, "kind": "function", "displayName": "Header As", "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).", "ognl": false, "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", "ognl": false, "suffix": "}" }, + "header.name": { "index": 25, "kind": "function", "displayName": "Header", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message header with the given name", "ognl": true, "suffix": "}" }, + "variableAs(key,type)": { "index": 26, "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": 27, "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": "}" }, + "variable.name": { "index": 28, "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": "}" }, + "exchangeProperty.name": { "index": 29, "kind": "function", "displayName": "Exchange Property", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The exchange property with the given name", "ognl": true, "suffix": "}" }, + "camelContext": { "index": 30, "kind": "function", "displayName": "Camel Context", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Camel Context", "ognl": true, "suffix": "}" }, + "jq(input,exp)": { "index": 31, "kind": "function", "displayName": "JQ", "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 (optional), you can [...] + "jsonpath(input,exp)": { "index": 32, "kind": "function", "displayName": "JSonPath", "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. For i [...] + "xpath(input,exp)": { "index": 33, "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 (optional [...] + "sys.name": { "index": 34, "kind": "function", "displayName": "JVM System Property", "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", "ognl": false, "suffix": "}" }, + "env.name": { "index": 35, "kind": "function", "displayName": "OS Environment Variable", "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", "ognl": false, "suffix": "}" }, + "pretty(exp)": { "index": 36, "kind": "function", "displayName": "Pretty Print", "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.", "ognl": false, "suffix": "}" }, + "date(command)": { "index": 37, "kind": "function", "displayName": "Parse Date", "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 ob [...] + "date-with-timezone(command:timezone:pattern)": { "index": 38, "kind": "function", "displayName": "Date Formatter", "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, `exchangeCreated` for the timesta [...] + "bean(name.method)": { "index": 39, "kind": "function", "displayName": "Call Java Bean", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Calls a Java bean. The name of the bean can also refer to a class name using type prefix as follows `bean:type:com.foo.MyClass`. If no method name is given then Camel will automatic attempt to find the b [...] + "propertiesExist:key": { "index": 40, "kind": "function", "displayName": "Property Placeholder Exists", "group": "function", "label": "function", "required": false, "javaType": "boolean", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Checks whether a property placeholder with the given key exists or not. The result can be negated by prefixing the key with !", "ognl": false, "suffix": "}" }, + "properties:key:default": { "index": 41, "kind": "function", "displayName": "Property Placeholder", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Lookup a property placeholder with the given key. If the key does not exist nor has a value, then an optional default value can be specified.", "ognl": false, "suffix": "}" }, + "ref:name": { "index": 42, "kind": "function", "displayName": "Bean By Id", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To look up a bean from the Registry with the given name.", "ognl": false, "suffix": "}" }, + "type:name.field": { "index": 43, "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`", " [...] + "replace(from,to,exp)": { "index": 44, "kind": "function", "displayName": "Replace String Values", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Replace all the string values in the message body\/expression. To make it easier to replace single and double quotes, then you can use XML escaped values `\\"` as double quote, `\\'` [...] + "substring(head,tail)": { "index": 45, "kind": "function", "displayName": "Substring", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a substring of the message body\/expression. If only one positive number, then the returned string is clipped from the beginning. If only one negative number, then the returned string is clipped fr [...] + "random(min,max)": { "index": 46, "kind": "function", "displayName": "Generate Random Number", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a random number between min (included) and max (excluded).", "ognl": false, "suffix": "}" }, + "skip(num)": { "index": 47, "kind": "function", "displayName": "Skip First Items from the Message Body", "group": "function", "label": "function", "required": false, "javaType": "java.util.Iterator", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The skip function iterates the message body and skips the first number of items. This can be used with the Splitter EIP to split a message body and skip the first N number of [...] + "collate(num)": { "index": 48, "kind": "function", "displayName": "Group Message Body into Sub Lists", "group": "function", "label": "function", "required": false, "javaType": "java.util.Iterator", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The collate function iterates the message body and groups the data into sub lists of specified size. This can be used with the Splitter EIP to split a message body and group\/ba [...] + "join(separator,prefix,exp)": { "index": 49, "kind": "function", "displayName": "Join", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The join function iterates the message body\/expression and joins the data into a string. The separator is by default a comma. The prefix is optional. The join uses the message body as source by default. [...] + "messageHistory(boolean)": { "index": 50, "kind": "function", "displayName": "Print Message History", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message history of the current exchange (how it has been routed). This is similar to the route stack-trace message history the error handler logs in case of an unhandled exception. The b [...] + "uuid(type)": { "index": 51, "kind": "function", "displayName": "Generate UUID", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a UUID using the Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and `simple` as the type. If no type is given, the default is used. It is also possible to use a custom `UuidG [...] + "hash(exp,algorithm)": { "index": 52, "kind": "function", "displayName": "Compute Hash Value", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a hashed value (string in hex decimal) of the message body\/expression using JDK MessageDigest. The algorithm can be SHA-256 (default) or SHA3-256.", "ognl": false, "suffix": "}" }, + "empty(type)": { "index": 53, "kind": "function", "displayName": "Create Empty Object", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Creates a new empty object (decided by type). Use `string` to create an empty String. Use `list` to create an empty `java.util.ArrayList`. Use `map` to create an empty `java.util.HashMap`.", "ognl": false [...] + "iif(predicate,trueExp,falseExp)": { "index": 54, "kind": "function", "displayName": "If Then Else", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Evaluates the predicate and returns the value of trueExp or falseExp. This function is similar to the ternary operator in Java.", "ognl": false, "suffix": "}" } } } diff --git a/core/camel-api/src/generated/java/org/apache/camel/spi/annotations/Language.java b/core/camel-api/src/generated/java/org/apache/camel/spi/annotations/Language.java index 1a986577836..a619f4e481e 100644 --- a/core/camel-api/src/generated/java/org/apache/camel/spi/annotations/Language.java +++ b/core/camel-api/src/generated/java/org/apache/camel/spi/annotations/Language.java @@ -30,4 +30,17 @@ public @interface Language { String value(); + /** + * The class that contains all the name of functions that are supported by the language. The name of the functions + * are defined as {@code String} constants in the functions class. + * <p/> + * The class to provide can be any class but by convention, we would expect a class whose name is of type + * <i>xxxConstants</i> where <i>xxx</i> is the name of the corresponding language like for example + * <i>SimpleConstants</i> for the language <i>camel-simple</i>. + * <p/> + * The metadata of a given functions are retrieved directly from the annotation {@code @Metadata} added to the + * {@code String} constant representing its name and defined in the functions class. + */ + Class<?> functionsClass() default void.class; + } diff --git a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/file.json b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/file.json index 83d94c000d3..16ae6217ad2 100644 --- a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/file.json +++ b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/file.json @@ -20,5 +20,22 @@ "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax" }, "resultType": { "index": 2, "kind": "attribute", "displayName": "Result Type", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the class of the result type (type from output)" }, "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": { + "file:name": { "index": 0, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file name (relative from starting directory)", "ognl": false, "suffix": "}" }, + "file:name.noext": { "index": 1, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file name (relative from starting directory) without extension", "ognl": false, "suffix": "}" }, + "file:name.noext.single": { "index": 2, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file name (relative from starting directory) without extension. If the file name has multiple dots, then this expression strips and only returns the last part.", "ognl": false, "suffix": "}" }, + "file:name.ext": { "index": 3, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file extension", "ognl": false, "suffix": "}" }, + "file:name.ext.single": { "index": 4, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file extension. If the file extension has multiple dots, then this expression strips and only returns the last part.", "ognl": false, "suffix": "}" }, + "file:onlyname": { "index": 5, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "\u2020he file name (without any leading paths)", "ognl": false, "suffix": "}" }, + "file:onlyname.noext": { "index": 6, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "\u2020he file name (without any leading paths) without extension", "ognl": false, "suffix": "}" }, + "file:onlyname.noext.single": { "index": 7, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "\u2020he file name (without any leading paths) without extension. If the file name has multiple dots, then this expression strips and only returns the last part.", "ognl": false, "suffix": "}" }, + "file:parent": { "index": 8, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file parent directory (null if no parent directory)", "ognl": false, "suffix": "}" }, + "file:path": { "index": 9, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file path", "ognl": false, "suffix": "}" }, + "file:absolute": { "index": 10, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "boolean", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Whether the file is regarded as absolute or relative", "ognl": false, "suffix": "}" }, + "file:absolute.path": { "index": 11, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The absolute file path", "ognl": false, "suffix": "}" }, + "file:length": { "index": 12, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the file", "ognl": false, "suffix": "}" }, + "file:size": { "index": 13, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the file", "ognl": false, "suffix": "}" }, + "file:modified": { "index": 14, "kind": "function", "displayName": "File", "group": "function", "label": "function", "required": false, "javaType": "long", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The file modification date", "ognl": false, "suffix": "}" } } } 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 223741d6576..2fa67ebaf9d 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 @@ -20,5 +20,62 @@ "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax" }, "resultType": { "index": 2, "kind": "attribute", "displayName": "Result Type", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the class of the result type (type from output)" }, "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", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message body", "ognl": true, "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.", "ognl": false, "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.", "ognl": false, "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).", "ognl": false, "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", "ognl": false, "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", "ognl": false, "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 current exchange", "ognl": true, "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.", "ognl": true, "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.", "ognl": false, "suffix": "}" }, + "exception.stackTrace": { "index": 10, "kind": "function", "displayName": "Exception Stacktrace", "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.", "ognl": false, "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.", "ognl": false, "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.", "ognl": false, "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).", "ognl": false, "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", "ognl": false, "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", "ognl": false, "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.", "ognl": false, "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.", "ognl": false, "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.", "ognl": false, "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", "ognl": false, "suffix": "}" }, + "messageAs(type)": { "index": 20, "kind": "function", "displayName": "Message As", "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).", "ognl": true, "suffix": "}" }, + "bodyAs(type)": { "index": 21, "kind": "function", "displayName": "Body As", "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).", "ognl": true, "suffix": "}" }, + "mandatoryBodyAs(type)": { "index": 22, "kind": "function", "displayName": "Mandatory Body As", "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", "ognl": true, "suffix": "}" }, + "headerAs(key,type)": { "index": 23, "kind": "function", "displayName": "Header As", "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).", "ognl": false, "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", "ognl": false, "suffix": "}" }, + "header.name": { "index": 25, "kind": "function", "displayName": "Header", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message header with the given name", "ognl": true, "suffix": "}" }, + "variableAs(key,type)": { "index": 26, "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": 27, "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": "}" }, + "variable.name": { "index": 28, "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": "}" }, + "exchangeProperty.name": { "index": 29, "kind": "function", "displayName": "Exchange Property", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The exchange property with the given name", "ognl": true, "suffix": "}" }, + "camelContext": { "index": 30, "kind": "function", "displayName": "Camel Context", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Camel Context", "ognl": true, "suffix": "}" }, + "jq(input,exp)": { "index": 31, "kind": "function", "displayName": "JQ", "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 (optional), you can [...] + "jsonpath(input,exp)": { "index": 32, "kind": "function", "displayName": "JSonPath", "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. For i [...] + "xpath(input,exp)": { "index": 33, "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 (optional [...] + "sys.name": { "index": 34, "kind": "function", "displayName": "JVM System Property", "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", "ognl": false, "suffix": "}" }, + "env.name": { "index": 35, "kind": "function", "displayName": "OS Environment Variable", "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", "ognl": false, "suffix": "}" }, + "pretty(exp)": { "index": 36, "kind": "function", "displayName": "Pretty Print", "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.", "ognl": false, "suffix": "}" }, + "date(command)": { "index": 37, "kind": "function", "displayName": "Parse Date", "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 ob [...] + "date-with-timezone(command:timezone:pattern)": { "index": 38, "kind": "function", "displayName": "Date Formatter", "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, `exchangeCreated` for the timesta [...] + "bean(name.method)": { "index": 39, "kind": "function", "displayName": "Call Java Bean", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Calls a Java bean. The name of the bean can also refer to a class name using type prefix as follows `bean:type:com.foo.MyClass`. If no method name is given then Camel will automatic attempt to find the b [...] + "propertiesExist:key": { "index": 40, "kind": "function", "displayName": "Property Placeholder Exists", "group": "function", "label": "function", "required": false, "javaType": "boolean", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Checks whether a property placeholder with the given key exists or not. The result can be negated by prefixing the key with !", "ognl": false, "suffix": "}" }, + "properties:key:default": { "index": 41, "kind": "function", "displayName": "Property Placeholder", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Lookup a property placeholder with the given key. If the key does not exist nor has a value, then an optional default value can be specified.", "ognl": false, "suffix": "}" }, + "ref:name": { "index": 42, "kind": "function", "displayName": "Bean By Id", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To look up a bean from the Registry with the given name.", "ognl": false, "suffix": "}" }, + "type:name.field": { "index": 43, "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`", " [...] + "replace(from,to,exp)": { "index": 44, "kind": "function", "displayName": "Replace String Values", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Replace all the string values in the message body\/expression. To make it easier to replace single and double quotes, then you can use XML escaped values `\\"` as double quote, `\\'` [...] + "substring(head,tail)": { "index": 45, "kind": "function", "displayName": "Substring", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a substring of the message body\/expression. If only one positive number, then the returned string is clipped from the beginning. If only one negative number, then the returned string is clipped fr [...] + "random(min,max)": { "index": 46, "kind": "function", "displayName": "Generate Random Number", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a random number between min (included) and max (excluded).", "ognl": false, "suffix": "}" }, + "skip(num)": { "index": 47, "kind": "function", "displayName": "Skip First Items from the Message Body", "group": "function", "label": "function", "required": false, "javaType": "java.util.Iterator", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The skip function iterates the message body and skips the first number of items. This can be used with the Splitter EIP to split a message body and skip the first N number of [...] + "collate(num)": { "index": 48, "kind": "function", "displayName": "Group Message Body into Sub Lists", "group": "function", "label": "function", "required": false, "javaType": "java.util.Iterator", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The collate function iterates the message body and groups the data into sub lists of specified size. This can be used with the Splitter EIP to split a message body and group\/ba [...] + "join(separator,prefix,exp)": { "index": 49, "kind": "function", "displayName": "Join", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The join function iterates the message body\/expression and joins the data into a string. The separator is by default a comma. The prefix is optional. The join uses the message body as source by default. [...] + "messageHistory(boolean)": { "index": 50, "kind": "function", "displayName": "Print Message History", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message history of the current exchange (how it has been routed). This is similar to the route stack-trace message history the error handler logs in case of an unhandled exception. The b [...] + "uuid(type)": { "index": 51, "kind": "function", "displayName": "Generate UUID", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a UUID using the Camel `UuidGenerator`. You can choose between `default`, `classic`, `short` and `simple` as the type. If no type is given, the default is used. It is also possible to use a custom `UuidG [...] + "hash(exp,algorithm)": { "index": 52, "kind": "function", "displayName": "Compute Hash Value", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a hashed value (string in hex decimal) of the message body\/expression using JDK MessageDigest. The algorithm can be SHA-256 (default) or SHA3-256.", "ognl": false, "suffix": "}" }, + "empty(type)": { "index": 53, "kind": "function", "displayName": "Create Empty Object", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Creates a new empty object (decided by type). Use `string` to create an empty String. Use `list` to create an empty `java.util.ArrayList`. Use `map` to create an empty `java.util.HashMap`.", "ognl": false [...] + "iif(predicate,trueExp,falseExp)": { "index": 54, "kind": "function", "displayName": "If Then Else", "group": "function", "label": "function", "required": false, "javaType": "Object", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Evaluates the predicate and returns the value of trueExp or falseExp. This function is similar to the ternary operator in Java.", "ognl": false, "suffix": "}" } } } diff --git a/core/camel-core-languages/src/main/docs/modules/languages/pages/file-language.adoc b/core/camel-core-languages/src/main/docs/modules/languages/pages/file-language.adoc index bab3431944f..e8ae85b3f78 100644 --- a/core/camel-core-languages/src/main/docs/modules/languages/pages/file-language.adoc +++ b/core/camel-core-languages/src/main/docs/modules/languages/pages/file-language.adoc @@ -60,7 +60,7 @@ directory, see note below) |file:name.noext.single |String |yes |no |yes |no |refers to the file name with no extension (is relative to the starting directory, see note below). If the file -extension has multiple dots, then this expression strips only the last +name has multiple dots, then this expression strips only the last part, and keeps the others. |file:onlyname |String |yes |no |yes |no |refers to the file name only with no leading paths. 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 ac47f5fafee..3182c19c9a5 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 @@ -75,7 +75,7 @@ OGNL expression. |id |String |the message id -|messageTimestamp |String |the message timestamp (millis since epoc) that this message originates from. +|messageTimestamp |long |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 exists. The message timestamp and exchange created are different. An exchange always has a created timestamp which is the @@ -197,7 +197,7 @@ to a bean class (such as calling a static method), then you can prefix with the not exist nor has a value, then an optional default value can be specified. -|propertiesExist:key |String |Checks whether a property placeholder with the given key exists or not. +|propertiesExist:key |boolean |Checks whether a property placeholder with the given key exists or not. The result can be negated by prefixing the key with `!`. |fromRouteId |String |Returns the original route id where this exchange was created. @@ -254,7 +254,7 @@ If the number is negative, then the returned string is clipped from the ending. If the number is positive, then the returned string is clipped from the beginning. If the number is negative, then the returned string is clipped from the ending. -|substring(num1,num2,exp) |String |replace all the string values in the given expression. +|substring(num1,num2,exp) |String |returns a substring of the given expression. If the number is positive, then the returned string is clipped from the beginning. If the number is negative, then the returned string is clipped from the ending. diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/FileConstants.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/FileConstants.java new file mode 100644 index 00000000000..d093c39e34b --- /dev/null +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/FileConstants.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.language.simple; + +import org.apache.camel.spi.Metadata; + +@Metadata(label = "function", annotations = { "prefix=${", "suffix=}" }) +public final class FileConstants { + + @Metadata(description = "The file name (relative from starting directory)", javaType = "String", label = "function") + public static final String FILE_NAME = "file:name"; + @Metadata(description = "The file name (relative from starting directory) without extension", javaType = "String", + label = "function") + public static final String FILE_NO_EXT = "file:name.noext"; + @Metadata(description = "The file name (relative from starting directory) without extension. If the file name has multiple dots, then this expression strips and only returns the last part.", + javaType = "String", label = "function") + public static final String FILE_NO_EXT_SINGLE = "file:name.noext.single"; + @Metadata(description = "The file extension", javaType = "String", label = "function") + public static final String FILE_EXT = "file:name.ext"; + @Metadata(description = "The file extension. If the file extension has multiple dots, then this expression strips and only returns the last part.", + javaType = "String", label = "function") + public static final String FILE_EXT_SINGLE = "file:name.ext.single"; + @Metadata(description = "†he file name (without any leading paths)", javaType = "String", label = "function") + public static final String FILE_ONLY_NAME = "file:onlyname"; + @Metadata(description = "†he file name (without any leading paths) without extension", javaType = "String", + label = "function") + public static final String FILE_ONLY_NAME_NO_EXT = "file:onlyname.noext"; + @Metadata(description = "†he file name (without any leading paths) without extension. If the file name has multiple dots, then this expression strips and only returns the last part.", + javaType = "String", label = "function") + public static final String FILE_ONLY_NAME_NO_EXT_SINGLE = "file:onlyname.noext.single"; + @Metadata(description = "The file parent directory (null if no parent directory)", javaType = "String", label = "function") + public static final String FILE_PARENT = "file:parent"; + @Metadata(description = "The file path", javaType = "String", label = "function") + public static final String FILE_PATH = "file:path"; + @Metadata(description = "Whether the file is regarded as absolute or relative", javaType = "boolean", label = "function") + public static final String FILE_ABSOLUTE = "file:absolute"; + @Metadata(description = "The absolute file path", javaType = "String", label = "function") + public static final String FILE_ABSOLUTE_PATH = "file:absolute.path"; + @Metadata(description = "The size of the file", javaType = "long", label = "function") + public static final String FILE_LENGTH = "file:length"; + @Metadata(description = "The size of the file", javaType = "long", label = "function") + public static final String FILE_SIZE = "file:size"; + @Metadata(description = "The file modification date", javaType = "long", label = "function") + public static final String FILE_MODIFIED = "file:modified"; +} diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/FileLanguage.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/FileLanguage.java index 83b535c9f82..f579745e989 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/FileLanguage.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/FileLanguage.java @@ -21,7 +21,7 @@ import org.apache.camel.spi.annotations.Language; /** * The Camel file language. */ -@Language("file") +@Language(value = "file", functionsClass = FileConstants.class) public class FileLanguage extends SimpleLanguage { public FileLanguage() { 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 new file mode 100644 index 00000000000..a4be0023117 --- /dev/null +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleConstants.java @@ -0,0 +1,215 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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,ognl") + public static final String BODY = "body"; + @Metadata(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.", + javaType = "String", label = "function") + public static final String PRETTY_BODY = "prettyBody"; + @Metadata(description = "Converts the body to a String and removes all line-breaks, so the string is in one line.", + javaType = "String", label = "function") + public static final String BODY_ONE_LINE = "bodyOneLine"; + @Metadata(description = "The original incoming body (only available if allowUseOriginalMessage=true).", javaType = "Object", + label = "function") + public static final String ORIGINAL_BODY = "originalBody"; + @Metadata(description = "The message id", javaType = "String", label = "function") + public static final String ID = "id"; + @Metadata(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 exists." + + " The message timestamp and exchange created are different. An exchange always has a created timestamp which is the" + + " local timestamp when Camel created the exchange. The message timestamp is only available in some Camel components" + + " when the consumer is able to extract the timestamp from the source event." + + " If the message has no timestamp, then 0 is returned.", + javaType = "long", label = "function") + public static final String MESSAGE_TIMESTAMP = "messageTimestamp"; + @Metadata(description = "The exchange id", javaType = "String", label = "function") + public static final String EXCHANGE_ID = "exchangeId"; + @Metadata(description = "The current exchange", javaType = "org.apache.camel.Exchange", label = "function,ognl") + public static final String EXCHANGE = "exchange"; + @Metadata(description = "The exception object on the exchange (also from caught exceptions), is null if no exception present.", + javaType = "java.lang.Exception", label = "function,ognl") + public static final String EXCEPTION = "exception"; + @Metadata(description = "The exception message (also from caught exceptions), is null if no exception present.", + javaType = "String", label = "function", displayName = "Exception Message") + public static final String EXCEPTION_MESSAGE = "exception.message"; + @Metadata(description = "The exception stacktrace (also from caught exceptions), is null if no exception present.", + javaType = "String", label = "function", displayName = "Exception Stacktrace") + public static final String EXCEPTION_STACKTRACE = "exception.stackTrace"; + @Metadata(description = "Returns the id of the current thread. Can be used for logging.", javaType = "long", + label = "function") + public static final String THREAD_ID = "threadId"; + @Metadata(description = "Returns the name of the current thread. Can be used for logging.", javaType = "String", + label = "function") + public static final String THREAD_NAME = "threadName"; + @Metadata(description = "Returns the local hostname (may be empty if not possible to resolve).", javaType = "String", + label = "function") + public static final String HOST_NAME = "hostName"; + @Metadata(description = "The name of the CamelContext", javaType = "String", label = "function") + public static final String CAMEL_ID = "camelId"; + @Metadata(description = "The route id of the current route the Exchange is being routed", javaType = "String", + label = "function") + public static final String ROUTE_ID = "routeId"; + @Metadata(description = "The original route id where this exchange was created.", javaType = "String", label = "function") + public static final String FROM_ROUTE_ID = "fromRouteId"; + @Metadata(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.", + javaType = "String", label = "function") + public static final String ROUTE_GROUP = "routeGroup"; + @Metadata(description = "Returns the id of the current step the Exchange is being routed.", javaType = "String", + label = "function") + 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,ognl", javaType = "Object") + public static final String MESSAGE_AS = "messageAs(type)"; + @Metadata(description = "Converts the message body to the given type (classname).", label = "function,ognl", + 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,ognl", 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 = "The message header with the given name", label = "function,ognl", javaType = "Object") + public static final String HEADER = "header.name"; + @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 = "The variable with the given name", label = "function,ognl", javaType = "Object") + public static final String VARIABLE = "variable.name"; + @Metadata(description = "The exchange property with the given name", label = "function,ognl", javaType = "Object") + public static final String EXCHANGE_PROPERTY = "exchangeProperty.name"; + @Metadata(description = "The Camel Context", label = "function,ognl", javaType = "Object") + public static final String CAMEL_CONTEXT = "camelContext"; + @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 (optional), 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", displayName = "JQ") + public static final String JQ = "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." + + " For input (optional), 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", displayName = "JSonPath") + public static final String JSONPATH = "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." + + " For input (optional), 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", displayName = "XPath") + public static final String XPATH = "xpath(input,exp)"; + @Metadata(description = "The JVM system property with the given name", label = "function", javaType = "Object", + displayName = "JVM System Property") + public static final String SYS = "sys.name"; + @Metadata(description = "The OS environment variable with the given name", label = "function", javaType = "Object", + displayName = "OS Environment Variable") + 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", displayName = "Pretty Print") + 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", displayName = "Parse 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", displayName = "Date Formatter") + public static final String DATE_WITH_TIMEZONE = "date-with-timezone(command:timezone:pattern)"; + @Metadata(description = "Calls a Java bean." + + " The name of the bean can also refer to a class name using type prefix as follows `bean:type:com.foo.MyClass`." + + " If no method name is given then Camel will automatic attempt to find the best method to use.", + label = "function", javaType = "Object", displayName = "Call Java Bean") + public static final String BEAN = "bean(name.method)"; + @Metadata(description = "Checks whether a property placeholder with the given key exists or not. The result can be negated by prefixing the key with !", + label = "function", javaType = "boolean", displayName = "Property Placeholder Exists") + public static final String PROPERTIES_EXIST = "propertiesExist:key"; + @Metadata(description = "Lookup a property placeholder with the given key. If the key does not exist nor has a value, then an optional default value can be specified.", + label = "function", javaType = "String", displayName = "Property Placeholder") + public static final String PROPERTIES = "properties:key:default"; + @Metadata(description = "To look up a bean from the Registry with the given name.", label = "function", javaType = "Object", + displayName = "Bean By Id") + public static final String REF = "ref:name"; + @Metadata(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`", + label = "function", javaType = "Object", displayName = "Java Field Value") + public static final String TYPE = "type:name.field"; + @Metadata(description = "Replace all the string values in the message body/expression." + + " To make it easier to replace single and double quotes, then you can use XML escaped values `\\"` as double quote, `\\'` as single quote, and `\\∅` as empty value.", + label = "function", javaType = "String", displayName = "Replace String Values") + public static final String REPLACE = "replace(from,to,exp)"; + @Metadata(description = "Returns a substring of the message body/expression." + + " If only one positive number, then the returned string is clipped from the beginning." + + " If only one negative number, then the returned string is clipped from the beginning." + + " Otherwise the returned string is clipped between the head and tail positions.", + label = "function", javaType = "String") + public static final String SUBSTRING = "substring(head,tail)"; + @Metadata(description = "Returns a random number between min (included) and max (excluded).", label = "function", + javaType = "int", displayName = "Generate Random Number") + public static final String RANDOM = "random(min,max)"; + @Metadata(description = "The skip function iterates the message body and skips the first number of items." + + " This can be used with the Splitter EIP to split a message body and skip the first N number of items.", + label = "function", javaType = "java.util.Iterator", displayName = "Skip First Items from the Message Body") + public static final String SKIP = "skip(num)"; + @Metadata(description = "The collate function iterates the message body and groups the data into sub lists of specified size." + + " This can be used with the Splitter EIP to split a message body and group/batch" + + " the split sub message into a group of N sub lists.", + label = "function", javaType = "java.util.Iterator", displayName = "Group Message Body into Sub Lists") + public static final String COLLATE = "collate(num)"; + @Metadata(description = "The join function iterates the message body/expression and joins the data into a string." + + " The separator is by default a comma. The prefix is optional." + + " The join uses the message body as source by default. It is possible to refer to another" + + " source (simple language) such as a header via the exp parameter. For example `join('&','id=','$\\{header.ids}')`.", + label = "function", javaType = "String") + public static final String JOIN = "join(separator,prefix,exp)"; + @Metadata(description = "The message history of the current exchange (how it has been routed). This is similar to the route stack-trace message history" + + " the error handler logs in case of an unhandled exception." + + " The boolean can be used to turn off detailed information to be less verbose, and avoid printing sensitive data from the message.", + label = "function", javaType = "String", displayName = "Print Message History") + public static final String MESSAGE_HISTORY = "messageHistory(boolean)"; + @Metadata(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 `UuidGenerator`" + + " and bind the bean to the xref:manual::registry.adoc[Registry] with an id. For example `${uuid(myGenerator)}`" + + " where the ID is _myGenerator_.", + label = "function", javaType = "String", displayName = "Generate UUID") + public static final String UUID = "uuid(type)"; + @Metadata(description = "Returns a hashed value (string in hex decimal) of the message body/expression using JDK MessageDigest. The algorithm can be SHA-256 (default) or SHA3-256.", + label = "function", javaType = "String", displayName = "Compute Hash Value") + public static final String HASH = "hash(exp,algorithm)"; + @Metadata(description = "Creates a new empty object (decided by type). Use `string` to create an empty String. Use `list` to create an empty `java.util.ArrayList`. Use `map` to create an empty `java.util.HashMap`.", + label = "function", javaType = "Object", displayName = "Create Empty Object") + public static final String EMPTY = "empty(type)"; + @Metadata(description = "Evaluates the predicate and returns the value of trueExp or falseExp. This function is similar to the ternary operator in Java.", + label = "function", javaType = "Object", displayName = "If Then Else") + public static final String IIF = "iif(predicate,trueExp,falseExp)"; +} diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java index 723c34b3e2d..85c4b07d7bf 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java @@ -37,7 +37,7 @@ import org.slf4j.LoggerFactory; /** * The Camel simple language. */ -@Language("simple") +@Language(value = "simple", functionsClass = SimpleConstants.class) public class SimpleLanguage extends LanguageSupport implements StaticService { private static final Logger LOG = LoggerFactory.getLogger(SimpleLanguage.class); diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/support/Schema.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/support/Schema.java index fab0841b324..864c83c73b7 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/support/Schema.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/support/Schema.java @@ -31,6 +31,8 @@ public class Schema { public ObjectNode properties; @JsonIgnore public ObjectNode exchangeProperties; + @JsonProperty + public ObjectNode functions; public Schema() { } 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 9cfd4e4ed36..249e1951cbc 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 @@ -413,6 +413,10 @@ public final class JsonMapper { JsonObject wrapper = new JsonObject(); wrapper.put("language", obj); wrapper.put("properties", asJsonObject(model.getOptions())); + final List<LanguageModel.LanguageFunctionModel> functions = model.getFunctions(); + if (!functions.isEmpty()) { + wrapper.put("functions", asJsonObjectFunctions(functions)); + } return wrapper; } @@ -599,6 +603,24 @@ 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); + jo.put("ognl", o.isOgnl()); + 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 f4bb4ddb395..36fd690f6f0 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 @@ -16,10 +16,14 @@ */ package org.apache.camel.tooling.model; +import java.util.ArrayList; +import java.util.List; + public class LanguageModel extends ArtifactModel<LanguageModel.LanguageOptionModel> { protected String modelName; protected String modelJavaType; + protected final List<LanguageFunctionModel> functions = new ArrayList<>(); public static class LanguageOptionModel extends BaseOptionModel { @@ -48,4 +52,70 @@ public class LanguageModel extends ArtifactModel<LanguageModel.LanguageOptionMod public void setModelJavaType(String modelJavaType) { this.modelJavaType = modelJavaType; } + + public List<LanguageFunctionModel> getFunctions() { + return functions; + } + + public void addFunction(LanguageFunctionModel function) { + functions.add(function); + } + + public static class LanguageFunctionModel extends BaseOptionModel { + + /** + * The name of the constant that defines the function. + */ + private String constantName; + + /** + * Whether this function allows to do OGNL method calls. + */ + boolean ognl; + + /** + * Optional prefix for the function + */ + private String prefix; + + /** + * Optional suffix for the function + */ + private String suffix; + + public String getConstantName() { + return constantName; + } + + public void setConstantName(String constantName) { + this.constantName = constantName; + } + + public boolean isOgnl() { + return ognl; + } + + public void setOgnl(boolean ognl) { + this.ognl = ognl; + } + + @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/AbstractGenerateConfigurerMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/AbstractGenerateConfigurerMojo.java index 504f774d1b2..f76a3e6fc3c 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/AbstractGenerateConfigurerMojo.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/AbstractGenerateConfigurerMojo.java @@ -518,4 +518,14 @@ public abstract class AbstractGenerateConfigurerMojo extends AbstractGeneratorMo return false; } + private static String asString(AnnotationInstance ai, String name) { + if (ai != null) { + AnnotationValue av = ai.value(name); + if (av != null) { + return av.asString(); + } + } + return null; + } + } 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 3a7d4eb9d37..81b8adf5b0c 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 @@ -18,6 +18,7 @@ package org.apache.camel.maven.packaging; import java.io.File; import java.io.IOException; +import java.lang.reflect.Field; import java.nio.file.Path; import java.util.Collections; import java.util.HashMap; @@ -26,7 +27,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.camel.maven.packaging.generics.ClassUtil; +import org.apache.camel.maven.packaging.generics.PackagePluginUtils; import org.apache.camel.spi.Metadata; +import org.apache.camel.spi.annotations.Language; import org.apache.camel.tooling.model.EipModel; import org.apache.camel.tooling.model.EipModel.EipOptionModel; import org.apache.camel.tooling.model.JsonMapper; @@ -34,6 +37,7 @@ import org.apache.camel.tooling.model.LanguageModel; import org.apache.camel.tooling.model.LanguageModel.LanguageOptionModel; import org.apache.camel.tooling.model.SupportLevel; import org.apache.camel.tooling.util.PackageHelper; +import org.apache.camel.tooling.util.Strings; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.logging.Log; @@ -42,6 +46,10 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectHelper; import org.codehaus.plexus.build.BuildContext; +import org.jboss.jandex.DotName; +import org.jboss.jandex.IndexView; + +import static java.lang.reflect.Modifier.isStatic; /** * Analyses the Camel plugins in a project and generates extra descriptor information for easier auto-discovery in @@ -50,6 +58,9 @@ import org.codehaus.plexus.build.BuildContext; @Mojo(name = "generate-languages-list", threadSafe = true) public class PackageLanguageMojo extends AbstractGeneratorMojo { + private static final DotName LANGUAGE = DotName.createSimple(Language.class.getName()); + private IndexView indexView; + /** * The output directory for generated languages file */ @@ -162,7 +173,7 @@ public class PackageLanguageMojo extends AbstractGeneratorMojo { SchemaHelper.addModelMetadata(languageModel, project); SchemaHelper.addModelMetadata(languageModel, javaType.getAnnotation(Metadata.class)); - // build json schema for the data format + // build json schema for the language String schema = JsonMapper.createParameterJsonSchema(languageModel); if (log.isDebugEnabled()) { log.debug("JSON schema\n" + schema); @@ -203,7 +214,7 @@ public class PackageLanguageMojo extends AbstractGeneratorMojo { return count; } - protected static LanguageModel extractLanguageModel(MavenProject project, String json, String name, Class<?> javaType) { + protected LanguageModel extractLanguageModel(MavenProject project, String json, String name, Class<?> javaType) { EipModel def = JsonMapper.generateEipModel(json); LanguageModel model = new LanguageModel(); model.setName(name); @@ -258,9 +269,86 @@ public class PackageLanguageMojo extends AbstractGeneratorMojo { option.setDescription(opt.getDescription()); model.addOption(option); } + + // read class and find functionClass and add each field as a function in the model + Class<?> classElement = loadClass(javaType.getName()); + final Language lan = classElement.getAnnotation(Language.class); + if (lan.functionsClass() != void.class) { + classElement = loadClass(lan.functionsClass().getName()); + if (classElement != null) { + for (Field field : classElement.getFields()) { + final boolean isEnum = classElement.isEnum(); + if ((isEnum || isStatic(field.getModifiers()) && field.getType() == String.class) + && field.isAnnotationPresent(Metadata.class)) { + try { + addFunction(model, field); + } catch (Exception e) { + getLog().warn(e); + } + } + } + } + } + return model; } + 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(); + // compute a display name if we don't have anything + if (Strings.isNullOrEmpty(displayName)) { + displayName = fun.getName(); + int pos = displayName.indexOf('('); + if (pos == -1) { + pos = displayName.indexOf(':'); + } + if (pos == -1) { + pos = displayName.indexOf('.'); + } + if (pos != -1) { + displayName = displayName.substring(0, pos); + } + displayName = displayName.replace('-', ' '); + displayName = Strings.asTitle(displayName); + } + fun.setDisplayName(displayName); + fun.setJavaType(metadata.javaType()); + fun.setRequired(metadata.required()); + fun.setDefaultValue(metadata.defaultValue()); + fun.setDeprecated(field.isAnnotationPresent(Deprecated.class)); + fun.setDeprecationNote(metadata.deprecationNote()); + fun.setSecret(metadata.secret()); + String label = metadata.label(); + boolean ognl = false; + if (label.contains(",ognl")) { + ognl = true; + label = label.replace(",ognl", ""); + } + String group = EndpointHelper.labelAsGroupName(label, false, false); + fun.setGroup(group); + fun.setLabel(label); + fun.setOgnl(ognl); + model.addFunction(fun); + } + private static String readClassFromCamelResource(File file, StringBuilder buffer, BuildContext buildContext) throws MojoExecutionException { // skip directories as there may be a sub .resolver directory such as in @@ -326,4 +414,11 @@ public class PackageLanguageMojo extends AbstractGeneratorMojo { return "META-INF/" + pckName.replace('.', '/'); } + private IndexView getIndex() { + if (indexView == null) { + indexView = PackagePluginUtils.readJandexIndexQuietly(project); + } + return indexView; + } + } diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/generics/ClassUtil.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/generics/ClassUtil.java index f15d3c1c401..6616cbcbbdd 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/generics/ClassUtil.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/generics/ClassUtil.java @@ -81,8 +81,7 @@ public final class ClassUtil { * type otherwise it return the casted {@link Class} of the type argument. * </p> * - * @param type class or parametrized type - * @return + * @param type class or parametrized type */ public static Class<?> getClass(Type type) { return getClazz(type); @@ -209,4 +208,5 @@ public final class ClassUtil { .map(annotation -> annotation.annotationType().getName()) .anyMatch(fqAnnotationName::equals); } + } diff --git a/tooling/spi-annotations/src/main/java/org/apache/camel/spi/annotations/Language.java b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/annotations/Language.java index 1a986577836..a619f4e481e 100644 --- a/tooling/spi-annotations/src/main/java/org/apache/camel/spi/annotations/Language.java +++ b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/annotations/Language.java @@ -30,4 +30,17 @@ public @interface Language { String value(); + /** + * The class that contains all the name of functions that are supported by the language. The name of the functions + * are defined as {@code String} constants in the functions class. + * <p/> + * The class to provide can be any class but by convention, we would expect a class whose name is of type + * <i>xxxConstants</i> where <i>xxx</i> is the name of the corresponding language like for example + * <i>SimpleConstants</i> for the language <i>camel-simple</i>. + * <p/> + * The metadata of a given functions are retrieved directly from the annotation {@code @Metadata} added to the + * {@code String} constant representing its name and defined in the functions class. + */ + Class<?> functionsClass() default void.class; + }