This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/master by this push: new d170870 CAMEL-11497 - Languages docs must be under camel-base, since autogenerated d170870 is described below commit d17087019f230ab2f3e3c5793c361d8a2597f972 Author: Andrea Cosentino <anco...@gmail.com> AuthorDate: Wed May 22 09:20:39 2019 +0200 CAMEL-11497 - Languages docs must be under camel-base, since autogenerated --- .../src/main/docs/constant-language.adoc | 59 ++ .../src/main/docs/exchangeProperty-language.adoc | 60 ++ core/camel-base/src/main/docs/file-language.adoc | 295 +++++++ core/camel-base/src/main/docs/header-language.adoc | 44 + core/camel-base/src/main/docs/ref-language.adoc | 57 ++ core/camel-base/src/main/docs/simple-language.adoc | 897 +++++++++++++++++++++ .../src/main/docs/tokenize-language.adoc | 38 + 7 files changed, 1450 insertions(+) diff --git a/core/camel-base/src/main/docs/constant-language.adoc b/core/camel-base/src/main/docs/constant-language.adoc new file mode 100644 index 0000000..c2e3a26 --- /dev/null +++ b/core/camel-base/src/main/docs/constant-language.adoc @@ -0,0 +1,59 @@ +[[constant-language]] +== Constant Language + +*Available as of Camel version 1.5* + +The Constant Expression Language is really just a way to specify +constant strings as a type of expression. + +NOTE: This is a fixed constant value that is only set once during starting up the route, + do not use this if you want dynamic values during routing. + +=== Constant Options + + +// language options: START +The Constant language supports 1 options, which are listed below. + + + +[width="100%",cols="2,1m,1m,6",options="header"] +|=== +| Name | Default | Java Type | Description +| trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks +|=== +// language options: END + + +=== Example usage + +The setHeader element of the Spring DSL can utilize a constant +expression like: + +[source,xml] +---- +<route> + <from uri="seda:a"/> + <setHeader headerName="theHeader"> + <constant>the value</constant> + </setHeader> + <to uri="mock:b"/> +</route> +---- + +in this case, the Message coming from the seda:a +Endpoint will have 'theHeader' header set to the +constant value 'the value'. + +And the same example using Java DSL: + +[source,java] +---- +from("seda:a") + .setHeader("theHeader", constant("the value")) + .to("mock:b"); +---- + +=== Dependencies + +The Constant language is part of *camel-core*. \ No newline at end of file diff --git a/core/camel-base/src/main/docs/exchangeProperty-language.adoc b/core/camel-base/src/main/docs/exchangeProperty-language.adoc new file mode 100644 index 0000000..163261e --- /dev/null +++ b/core/camel-base/src/main/docs/exchangeProperty-language.adoc @@ -0,0 +1,60 @@ +[[exchangeProperty-language]] +== ExchangeProperty Language + +*Available as of Camel version 2.0* + +The ExchangeProperty Expression Language allows you to extract values of +named exchange properties. + +=== Exchange Property Options + +// language options: START +The ExchangeProperty language supports 1 options, which are listed below. + + + +[width="100%",cols="2,1m,1m,6",options="header"] +|=== +| Name | Default | Java Type | Description +| trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks +|=== +// language options: END + +=== Example usage + +The recipientList element of the Spring DSL can utilize a +exchangeProperty expression like: + +In this case, the list of recipients are contained in the property +'myProperty'. + +[source,xml] +---- +<route> + <from uri="direct:a" /> + <recipientList> + <exchangeProperty>myProperty</exchangeProperty> + </recipientList> +</route> +---- + +And the same example in Java DSL: + +[source,java] +---- +from("direct:a").recipientList(exchangeProperty("myProperty")); +---- + +And with a slightly different syntax where you use the builder to the +fullest (i.e. avoid using parameters but using stacked operations, +notice that exchangeProperty is not a parameter but a stacked method +call) + +[source,java] +---- +from("direct:a").recipientList().exchangeProperty("myProperty"); +---- + +=== Dependencies + +The ExchangeProperty language is part of *camel-core*. \ No newline at end of file diff --git a/core/camel-base/src/main/docs/file-language.adoc b/core/camel-base/src/main/docs/file-language.adoc new file mode 100644 index 0000000..b4ec091 --- /dev/null +++ b/core/camel-base/src/main/docs/file-language.adoc @@ -0,0 +1,295 @@ +[[file-language]] +== File Language + +*Available as of Camel version 1.1* + +INFO:*File language is now merged with Simple language* +From Camel 2.2 onwards, the file language is now merged with +<<simple-language,Simple>> language which means you can use all the file +syntax directly within the simple language. + +The File Expression Language is an extension to the +<<simple-language,Simple>> language, adding file related capabilities. +These capabilities are related to common use cases working with file +path and names. The goal is to allow expressions to be used with the +File and FTP components for setting +dynamic file patterns for both consumer and producer. + +=== File Language options + +// language options: START +The File language supports 2 options, which are listed below. + + + +[width="100%",cols="2,1m,1m,6",options="header"] +|=== +| Name | Default | Java Type | Description +| resultType | | String | Sets the class name of the result type (type from output) +| trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks +|=== +// language options: END + +=== Syntax + +This language is an *extension* to the <<simple-language,Simple>> language +so the <<simple-language,Simple>> syntax applies also. So the table below +only lists the additional. + + As opposed to <<simple-language,Simple>> language +<<file-language,File Language>> also supports +<<constant-language,Constant>> expressions so you can enter a fixed +filename. + +All the file tokens use the same expression name as the method on the +`java.io.File` object, for instance `file:absolute` refers to the +`java.io.File.getAbsolute()` method. Notice that not all expressions are +supported by the current Exchange. For instance the <<ftp-component,FTP>> +component supports some of the options, where as the +File component supports all of them. + + +[width="100%",cols="10%,10%,10%,10%,10%,25%,25%",options="header",] +|=== +|Expression |Type |File Consumer |File Producer |FTP Consumer |FTP Producer |Description + +|file:name |String |yes |no |yes |no |refers to the file name (is relative to the starting directory, see note +below) + +|file:name.ext |String |yes |no |yes |no |*Camel 2.3:* refers to the file extension only + +|file:name.ext.single |String |yes |no |yes |no |*Camel 2.14.4/2.15.3:* refers to the file extension. If the file +extension has mutiple dots, then this expression strips and only returns +the last part. + +|file:name.noext |String |yes |no |yes |no |refers to the file name with no extension (is relative to the starting +directory, see note below) + +|file:name.noext.single |String |yes |no |yes |no |*Camel 2.14.4/2.15.3:* 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 +part, and keep the others. + +|file:onlyname |String |yes |no |yes |no |refers to the file name only with no leading paths. + +|file:onlyname.noext |String |yes |no |yes |no |refers to the file name only with no extension and with no leading +paths. + +|file:onlyname.noext.single |String |yes |no |yes |no |*Camel 2.14.4/2.15.3:*refers to the file name only with no extension and +with no leading paths. If the file extension has multiple dots, then +this expression strips only the last part, and keep the others. + +|file:ext |String |yes |no |yes |no |refers to the file extension only + +|file:parent |String |yes |no |yes |no |refers to the file parent + +|file:path |String |yes |no |yes |no |refers to the file path + +|file:absolute |Boolean |yes |no |no |no |refers to whether the file is regarded as absolute or relative + +|file:absolute.path |String |yes |no |no |no |refers to the absolute file path + +|file:length |Long |yes |no |yes |no |refers to the file length returned as a Long type + +|file:size |Long |yes |no |yes |no |*Camel 2.5:* refers to the file length returned as a Long type + +|file:modified |Date |yes |no |yes |no |Refers to the file last modified returned as a Date type + +|date:_command:pattern_ |String |yes |yes |yes |yes |for date formatting using the `java.text.SimpleDateFormat` patterns. Is +an *extension* to the <<simple-language,Simple>> language. Additional +command is: *file* (consumers only) for the last modified timestamp of +the file. Notice: all the commands from the <<simple-language,Simple>> +language can also be used. +|=== + +=== File token example + +==== Relative paths + +We have a `java.io.File` handle for the file `hello.txt` in the +following *relative* directory: `.\filelanguage\test`. And we configure +our endpoint to use this starting directory `.\filelanguage`. The file +tokens will return as: + +[width="100%",cols="50%,50%",options="header",] +|=== +|Expression |Returns + +|file:name |test\hello.txt + +|file:name.ext |txt + +|file:name.noext |test\hello + +|file:onlyname |hello.txt + +|file:onlyname.noext |hello + +|file:ext |txt + +|file:parent |filelanguage\test + +|file:path |filelanguage\test\hello.txt + +|file:absolute |false + +|file:absolute.path |\workspace\camel\camel-core\target\filelanguage\test\hello.txt +|=== + +==== Absolute paths + +We have a `java.io.File` handle for the file `hello.txt` in the +following *absolute* directory: +`\workspace\camel\camel-core\target\filelanguage\test`. And we configure +out endpoint to use the absolute starting directory +`\workspace\camel\camel-core\target\filelanguage`. The file tokens will +return as: + +[width="100%",cols="50%,50%",options="header",] +|=== +|Expression |Returns + +|file:name |test\hello.txt + +|file:name.ext |txt + +|file:name.noext |test\hello + +|file:onlyname |hello.txt + +|file:onlyname.noext |hello + +|file:ext |txt + +|file:parent |\workspace\camel\camel-core\target\filelanguage\test + +|file:path |\workspace\camel\camel-core\target\filelanguage\test\hello.txt + +|file:absolute |true + +|file:absolute.path |\workspace\camel\camel-core\target\filelanguage\test\hello.txt +|=== + +=== Samples + +You can enter a fixed <<constant-language,Constant>> expression such as +`myfile.txt`: + +[source] +---- +fileName="myfile.txt" +---- + +Lets assume we use the file consumer to read files and want to move the +read files to backup folder with the current date as a sub folder. This +can be archieved using an expression like: + +[source] +---- +fileName="backup/${date:now:yyyyMMdd}/${file:name.noext}.bak" +---- + +relative folder names are also supported so suppose the backup folder +should be a sibling folder then you can append .. as: + +[source] +---- +fileName="../backup/${date:now:yyyyMMdd}/${file:name.noext}.bak" +---- + +As this is an extension to the <<simple-language,Simple>> language we have +access to all the goodies from this language also, so in this use case +we want to use the in.header.type as a parameter in the dynamic +expression: + +[source] +---- +fileName="../backup/${date:now:yyyyMMdd}/type-${in.header.type}/backup-of-${file:name.noext}.bak" +---- + +If you have a custom Date you want to use in the expression then Camel +supports retrieving dates from the message header. + +[source] +---- +fileName="orders/order-${in.header.customerId}-${date:in.header.orderDate:yyyyMMdd}.xml" +---- + +And finally we can also use a bean expression to invoke a POJO class +that generates some String output (or convertible to String) to be used: + +[source] +---- +fileName="uniquefile-${bean:myguidgenerator.generateid}.txt" +---- + +And of course all this can be combined in one expression where you can +use the <<file-language,File Language>>, <<file-language,Simple>> +and the <<bean-component,Bean>> language in one combined expression. This +is pretty powerful for those common file path patterns. + +=== Using Spring PropertyPlaceholderConfigurer together with the File component + +In Camel you can use the <<file-language,File Language>> directly +from the <<simple-language,Simple>> language which makes a +Content Based Router easier to do in +Spring XML, where we can route based on file extensions as shown below: + +[source,xml] +---- +<from uri="file://input/orders"/> + <choice> + <when> + <simple>${file:ext} == 'txt'</simple> + <to uri="bean:orderService?method=handleTextFiles"/> + </when> + <when> + <simple>${file:ext} == 'xml'</simple> + <to uri="bean:orderService?method=handleXmlFiles"/> + </when> + <otherwise> + <to uri="bean:orderService?method=handleOtherFiles"/> + </otherwise> + </choice> +---- + +If you use the `fileName` option on the File endpoint +to set a dynamic filename using the <<file-language,File Language>> then make sure you + + use the alternative syntax (available from Camel 2.5 onwards) to avoid +clashing with Springs `PropertyPlaceholderConfigurer`. + +*bundle-context.xml* + +[source,xml] +---- +<bean id="propertyPlaceholder" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> + <property name="location" value="classpath:bundle-context.cfg" /> +</bean> + +<bean id="sampleRoute" class="SampleRoute"> + <property name="fromEndpoint" value="${fromEndpoint}" /> + <property name="toEndpoint" value="${toEndpoint}" /> +</bean> +---- + +*bundle-context.cfg* + +[source] +---- +fromEndpoint=activemq:queue:test +toEndpoint=file://fileRoute/out?fileName=test-$simple{date:now:yyyyMMdd}.txt +---- + +Notice how we use the $simple\{ } syntax in the `toEndpoint` above. + + If you don't do this, there is a clash and Spring will throw an +exception like + +[source,java] +---------------------------------------------------------------------------------------------------- +org.springframework.beans.factory.BeanDefinitionStoreException: +Invalid bean definition with name 'sampleRoute' defined in class path resource [bundle-context.xml]: +Could not resolve placeholder 'date:now:yyyyMMdd' +---------------------------------------------------------------------------------------------------- + +=== Dependencies + +The File language is part of *camel-core*. diff --git a/core/camel-base/src/main/docs/header-language.adoc b/core/camel-base/src/main/docs/header-language.adoc new file mode 100644 index 0000000..f50cc76 --- /dev/null +++ b/core/camel-base/src/main/docs/header-language.adoc @@ -0,0 +1,44 @@ +[[header-language]] +== Header Language + +*Available as of Camel version 1.5* + +The Header Expression Language allows you to extract values of named +headers. + +=== Header Options + +// language options: START +The Header language supports 1 options, which are listed below. + + + +[width="100%",cols="2,1m,1m,6",options="header"] +|=== +| Name | Default | Java Type | Description +| trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks +|=== +// language options: END + +=== Example usage + +The recipientList element of the Spring DSL can utilize a header +expression like: + +In this case, the list of recipients are contained in the header +'myHeader'. + +And the same example in Java DSL: + +And with a slightly different syntax where you use the builder to the +fullest (i.e. avoid using parameters but using stacked operations, +notice that header is not a parameter but a stacked method call) + +[source,java] +---- +from("direct:a").recipientList().header("myHeader"); +---- + +=== Dependencies + +The Header language is part of *camel-core*. \ No newline at end of file diff --git a/core/camel-base/src/main/docs/ref-language.adoc b/core/camel-base/src/main/docs/ref-language.adoc new file mode 100644 index 0000000..aa209e3 --- /dev/null +++ b/core/camel-base/src/main/docs/ref-language.adoc @@ -0,0 +1,57 @@ +[[ref-language]] +== Ref Language + +*Available as of Camel version 2.8* + +The Ref Expression Language is really just a way to lookup a custom +Expression or Predicate from the Registry. + +This is particular useable in XML DSLs. + +=== Ref Language options + +// language options: START +The Ref language supports 1 options, which are listed below. + + + +[width="100%",cols="2,1m,1m,6",options="header"] +|=== +| Name | Default | Java Type | Description +| trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks +|=== +// language options: END + +=== Example usage + +The Splitter in XML DSL can utilize a custom +expression using `<ref>` like: + +[source,xml] +---- +<bean id="myExpression" class="com.mycompany.MyCustomExpression"/> + +<route> + <from uri="seda:a"/> + <split> + <ref>myExpression</ref> + <to uri="mock:b"/> + </split> +</route> +---- + +in this case, the Message coming from the seda:a +Endpoint will be splitted using a custom +Expression which has the id `myExpression` in the +Registry. + +And the same example using Java DSL: + +[source,java] +---- +from("seda:a").split().ref("myExpression").to("seda:b"); +---- + +=== Dependencies + +The Ref language is part of *camel-core*. \ No newline at end of file diff --git a/core/camel-base/src/main/docs/simple-language.adoc b/core/camel-base/src/main/docs/simple-language.adoc new file mode 100644 index 0000000..fa1aff4 --- /dev/null +++ b/core/camel-base/src/main/docs/simple-language.adoc @@ -0,0 +1,897 @@ +[[simple-language]] +== Simple Language + +*Available as of Camel version 1.1* + +The Simple Expression Language was a really simple language when it was +created, but has since grown more powerful. It is primarily intended for +being a really small and simple language for evaluating +Expressions and Predicates +without requiring any new dependencies or knowledge of +<<xpath-language,XPath>>; so it is ideal for testing in camel-core. The +idea was to cover 95% of the common use cases when you need a little bit +of expression based script in your Camel routes. + +However for much more complex use cases you are generally recommended to +choose a more expressive and powerful language such as: + +* <<groovy-language,Groovy>> +* <<spel-language,SpEL>> +* <<mvel-component,MVEL>> +* <<ognl-language,OGNL>> + +The simple language uses `${body`} placeholders for complex expressions +where the expression contains constant literals. The $\{ } placeholders +can be omitted if the expression is only the token itself. + +TIP: *Alternative syntax* You can also use the alternative syntax which +uses `$simple{ }` as placeholders. This can be used in situations to avoid clashes when using for example +Spring property placeholder together with Camel. + + +=== Simple Language options + +// language options: START +The Simple language supports 2 options, which are listed below. + + + +[width="100%",cols="2,1m,1m,6",options="header"] +|=== +| Name | Default | Java Type | Description +| resultType | | String | Sets the class name of the result type (type from output) +| trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks +|=== +// language options: END + +=== Variables + +[width="100%",cols="10%,10%,80%",options="header",] +|======================================================================= +|Variable |Type |Description + +|camelId |String |the CamelContext name + +|camelContext.*OGNL* |Object |the CamelContext invoked using a Camel OGNL expression. + +|exchange |Exchange |the Exchange + +|exchange.*OGNL* |Object |the Exchange invoked using a Camel +OGNL expression. + +|exchangeId |String |the exchange id + +|id |String |the input message id + +|body |Object |the input body + +|in.body |Object |*deprecated* the input body + +|body.*OGNL* |Object |the input body invoked using a Camel OGNL expression. + +|in.body.*OGNL* |Object |*deprecated* the input body invoked using a Camel OGNL expression. + +|bodyAs(_type_) |Type |Converts the body to the given type determined by its +classname. The converted body can be null. + +|bodyAs(_type_).*OGNL* |Object |Converts the body to the given type determined by its +classname and then invoke methods using a Camel OGNL expression. The +converted body can be null. + +|mandatoryBodyAs(_type_) |Type |Converts the body to the given type determined by its +classname, and expects the body to be not null. + +|mandatoryBodyAs(_type_).*OGNL* |Object |Converts the body to the given type determined by its +classname and then invoke methods using a Camel OGNL expression. + +|out.body |Object |*deprecated* the output body + +|header.foo |Object |refer to the input foo header + +|header:foo |Object |refer to the input foo header + +|header[foo] |Object |refer to the input foo header + +|headers.foo |Object |refer to the input foo header + +|headers:foo |Object |refer to the input foo header + +|headers[foo] |Object |refer to the input foo header + +|in.header.foo |Object |*deprecated* refer to the input foo header + +|in.header:foo |Object |*deprecated* refer to the input foo header + +|in.header[foo] |Object |*deprecated* refer to the input foo header + +|in.headers.foo |Object |*deprecated* refer to the input foo header + +|in.headers:foo |Object |*deprecated* refer to the input foo header + +|in.headers[foo] |Object |*deprecated* refer to the input foo header + +|header.foo[bar] |Object |regard input foo header as a map and perform lookup on the +map with bar as key + +|in.header.foo[bar] |Object |*deprecated* regard input foo header as a map and perform lookup on the +map with bar as key + +|in.headers.foo[bar] |Object |*deprecated* regard input foo header as a map and perform lookup on the +map with bar as key + +|header.foo.*OGNL* |Object |refer to the input foo header and invoke its value using a +Camel OGNL expression. + +|in.header.foo.*OGNL* |Object |*deprecated* refer to the input foo header and invoke its value using a +Camel OGNL expression. + +|in.headers.foo.*OGNL* |Object |*deprecated* refer to the input foo header and invoke its value using a +Camel OGNL expression. + +|out.header.foo |Object |*deprecated* refer to the out header foo + +|out.header:foo |Object |*deprecated* refer to the out header foo + +|out.header[foo] |Object |*deprecated* refer to the out header foo + +|out.headers.foo |Object |*deprecated* refer to the out header foo + +|out.headers:foo |Object |*deprecated* refer to the out header foo + +|out.headers[foo] |Object |*deprecated* refer to the out header foo + +|headerAs(_key_,_type_) |Type |converts the header to the given type determined by its +classname + +|headers |Map |refer to the input headers + +|in.headers |Map |*deprecated* refer to the input headers + +|exchangeProperty.foo |Object |refer to the foo property on the exchange + +|exchangeProperty[foo] |Object |refer to the foo property on the exchange + +|exchangeProperty.foo.*OGNL* |Object |refer to the foo property on the exchange and invoke its +value using a Camel OGNL expression. + +|sys.foo |String |refer to the JVM system property + +|sysenv.foo |String |refer to the system environment variable + +|env.foo |String |refer to the system environment variable + +|exception |Object |refer to the exception object on the exchange, is *null* if +no exception set on exchange. Will fallback and grab caught exceptions +(`Exchange.EXCEPTION_CAUGHT`) if the Exchange has any. + +|exception.*OGNL* |Object |refer to the exchange exception invoked using a Camel OGNL +expression object + +|exception.message |String |refer to the exception.message on the exchange, is *null* if no +exception set on exchange. Will fallback and grab caught exceptions +(`Exchange.EXCEPTION_CAUGHT`) if the Exchange has any. + +|exception.stacktrace |String |refer to the exception.stracktrace on the exchange, is +*null* if no exception set on exchange. Will fallback and grab caught +exceptions (`Exchange.EXCEPTION_CAUGHT`) if the Exchange has any. + +|date:_command_ |Date |evaluates to a Date object. +Supported commands are: *now* for current timestamp, *in.header.xxx* or +*header.xxx* to use the Date object header with the key xxx. +*exchangeProperty.xxx* to use the 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 *in.header.xxx+1h* or even *now+1h30m-100*. + +|date:_command:pattern_ |String |Date formatting using `java.text.SimpleDataFormat` patterns. + +|date-with-timezone:_command:timezone:pattern_ |String |Date formatting using `java.text.SimpleDataFormat` timezones and patterns. + +|bean:_bean expression_ |Object |Invoking a bean expression using the <<bean-component,Bean>> language. +Specifying a method name you must use dot as separator. We also support +the ?method=methodname syntax that is used by the <<bean-component,Bean>> +component. + +|properties-location:_http://locationskey[locations:key]_ |String |Lookup a property with the given key. The `locations` +option is optional. See more at +Using PropertyPlaceholder. + +|`properties:key:default` |String |Lookup a property with the given key. If the key does +not exists or has no value, then an optional default value can be +specified. + +|routeId |String |Returns the id of the current route the +Exchange is being routed. + +|stepId |String |Returns the id of the current step the +Exchange is being routed. + +|threadName |String |Returns the name of the current thread. Can be used for +logging purpose. + +|ref:xxx |Object |To lookup a bean from the Registry with +the given id. + +|type:name.field |Object |To refer to a type or field by its FQN name. 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` + +|null |null |represents a *null* + +|random_(value)_ |Integer |returns a random Integer between 0 (included) and _value_ +(excluded) + +|random_(min,max)_ |Integer |returns a random Integer between _min_ (included) and +_max_ (excluded) + +|collate(group) |List |The collate function iterates the message body and groups +the data into sub lists of specified size. This can be used with the +Splitter EIP to split a message body and group/batch +the splitted sub message into a group of N sub lists. This method works +similar to the collate method in Groovy. + +|skip(number) |Iterator |The skip function iterates the message body and skips +the first number of items. This can be used with the +Splitter EIP to split a message body and skip the first N number of items. + +|messageHistory |String |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. + +|messageHistory(false) |String |As messageHistory but without the exchange details (only +includes the route strack-trace). This can be used if you do not want to +log sensitive data from the message itself. +|======================================================================= + +=== OGNL expression support + +INFO:Camel's OGNL support is for invoking methods only. You cannot access +fields. From *Camel 2.11.1* onwards we added special support for accessing the +length field of Java arrays. + + +The <<simple-language,Simple>> and <<simple-language,Bean>> language now +supports a Camel OGNL notation for invoking beans in a chain like +fashion. Suppose the Message IN body contains a POJO which has a `getAddress()` +method. + +Then you can use Camel OGNL notation to access the address object: + +[source,java] +-------------------------------- +simple("${body.address}") +simple("${body.address.street}") +simple("${body.address.zip}") +-------------------------------- + +Camel understands the shorthand names for getters, but you can invoke +any method or use the real name such as: + +[source,java] +-------------------------------------- +simple("${body.address}") +simple("${body.getAddress.getStreet}") +simple("${body.address.getZip}") +simple("${body.doSomething}") +-------------------------------------- + +You can also use the null safe operator (`?.`) to avoid NPE if for +example the body does NOT have an address + +[source,java] +---------------------------------- +simple("${body?.address?.street}") +---------------------------------- + +It is also possible to index in `Map` or `List` types, so you can do: + +[source,java] +--------------------------- +simple("${body[foo].name}") +--------------------------- + +To assume the body is `Map` based and lookup the value with `foo` as +key, and invoke the `getName` method on that value. + +If the key has space, then you *must* enclose the key with quotes, for +example 'foo bar': + +[source,java] +--------------------------------- +simple("${body['foo bar'].name}") +--------------------------------- + +You can access the `Map` or `List` objects directly using their key name +(with or without dots) : + +[source,java] +------------------------------ +simple("${body[foo]}") +simple("${body[this.is.foo]}") +------------------------------ + +Suppose there was no value with the key `foo` then you can use the null +safe operator to avoid the NPE as shown: + +[source,java] +---------------------------- +simple("${body[foo]?.name}") +---------------------------- + +You can also access `List` types, for example to get lines from the +address you can do: + +[source,java] +---------------------------------- +simple("${body.address.lines[0]}") +simple("${body.address.lines[1]}") +simple("${body.address.lines[2]}") +---------------------------------- + +There is a special `last` keyword which can be used to get the last +value from a list. + +[source,java] +------------------------------------- +simple("${body.address.lines[last]}") +------------------------------------- + +And to get the 2nd last you can subtract a number, so we can use +`last-1` to indicate this: + +[source,java] +--------------------------------------- +simple("${body.address.lines[last-1]}") +--------------------------------------- + +And the 3rd last is of course: + +[source,java] +--------------------------------------- +simple("${body.address.lines[last-2]}") +--------------------------------------- + +And you can call the size method on the list with + +[source,java] +------------------------------------ +simple("${body.address.lines.size}") +------------------------------------ + +From *Camel 2.11.1* onwards we added support for the length field for +Java arrays as well, eg: + +[source,java] +--------------------------------------------------- +String[] lines = new String[]{"foo", "bar", "cat"}; +exchange.getIn().setBody(lines); + +simple("There are ${body.length} lines") +--------------------------------------------------- + +And yes you can combine this with the operator support as shown below: + +[source,java] +------------------------------------ +simple("${body.address.zip} > 1000") +------------------------------------ + +=== Operator support + +The parser is limited to only support a single operator. + +To enable it the left value must be enclosed in $\{ }. The syntax is: + +[source] +-------------------------- +${leftValue} OP rightValue +-------------------------- + +Where the `rightValue` can be a String literal enclosed in `' '`, +`null`, a constant value or another expression enclosed in $\{ }. + +IMPORTANT: There *must* be spaces around the operator. + +Camel will automatically type convert the rightValue type to the +leftValue type, so it is able to eg. convert a string into a numeric so +you can use > comparison for numeric values. + +The following operators are supported: + +[width="100%",cols="50%,50%",options="header",] +|=== +|Operator |Description + +|== |equals + +|=~ |equals ignore case (will ignore case when comparing String values) + +|> |greater than + +|>= |greater than or equals + +|< |less than + +|<= |less than or equals + +|!=~ |not equals + +|!=~ |not equals ignore case (will ignore case when comparing String values) + +|contains |For testing if contains in a string based value + +|!contains |For testing if not contains in a string based value + +|~~ |For testing if contains by ignoring case sensitivity in a string based value + +|!~~ |For testing if not contains by ignoring case sensitivity in a string based value + +|regex |For matching against a given regular expression pattern defined as a +String value + +|!regex |For not matching against a given regular expression pattern defined as a +String value + +|in |For matching if in a set of values, each element must be separated by +comma. If you want to include an empty value, then it must be defined using double comma, eg ',,bronze,silver,gold', which +is a set of four values with an empty value and then the three medals. + +|!in |For matching if not in a set of values, each element must be separated +by comma. If you want to include an empty value, then it must be defined using double comma, eg ',,bronze,silver,gold', which +is a set of four values with an empty value and then the three medals. + +|is |For matching if the left hand side type is an instanceof the value. + +|!is |For matching if the left hand side type is not an instanceof the value. + +|range |For matching if the left hand side is within a range of values defined +as numbers: `from..to`.. + +|!range |For matching if the left hand side is not within a range of values +defined as numbers: `from..to`. . + +|startsWith |For testing if the left hand side string starts +with the right hand string. + +|endsWith |For testing if the left hand side string ends with +the right hand string. +|=== + +And the following unary operators can be used: + +[width="100%",cols="50%,50%",options="header",] +|=== +|Operator |Description + +|++ |To increment a number by one. The left hand side must be a +function, otherwise parsed as literal. + +|-- |To decrement a number by one. The left hand side must be a +function, otherwise parsed as literal. + +|\ |To escape a value, eg \$, to indicate a $ sign. +Special: Use \n for new line, \t for tab, and \r for carriage return. +*Notice:* Escaping is *not* supported using the +<<file-language,File Language>>. *Notice:* From Camel 2.11 +onwards the escape character is no longer support, but replaced with the +following three special escaping. + +|\n |To use newline character. + +|\t |To use tab character. + +|\r |To use carriage return character. + +|\} |To use the } character as text +|=== + +And the following logical operators can be used to group expressions: + +[width="100%",cols="50%,50%",options="header",] +|=== +|Operator |Description + +|&& |The logical and operator is used to group two expressions. + +| \|\| |The logical or operator is used to group two expressions. +|=== + +The syntax for AND is: + +[source] +---------------------------------------------------------- +${leftValue} OP rightValue && ${leftValue} OP rightValue +---------------------------------------------------------- + +And the syntax for OR is: + +[source] +--------------------------------------------------------- +${leftValue} OP rightValue || ${leftValue} OP rightValue +--------------------------------------------------------- + +Some examples: + +[source,java] +---- +// exact equals match +simple("${in.header.foo} == 'foo'") + +// ignore case when comparing, so if the header has value FOO this will match +simple("${in.header.foo} =~ 'foo'") + +// here Camel will type convert '100' into the type of in.header.bar and if it is an Integer '100' will also be converter to an Integer +simple("${in.header.bar} == '100'") + +simple("${in.header.bar} == 100") + +// 100 will be converter to the type of in.header.bar so we can do > comparison +simple("${in.header.bar} > 100") +---- + +==== Comparing with different types + +When you compare with different types such as String and int, then you +have to take a bit care. Camel will use the type from the left hand side +as 1st priority. And fallback to the right hand side type if both values +couldn't be compared based on that type. + + This means you can flip the values to enforce a specific type. Suppose +the bar value above is a String. Then you can flip the equation: + +[source,java] +---- +simple("100 < ${in.header.bar}") +---- + +which then ensures the int type is used as 1st priority. + +This may change in the future if the Camel team improves the binary +comparison operations to prefer numeric types over String based. It's +most often the String type which causes problem when comparing with +numbers. + +[source,java] +---- +// testing for null +simple("${in.header.baz} == null") + +// testing for not null +simple("${in.header.baz} != null") +---- + +And a bit more advanced example where the right value is another +expression + +[source,java] +---- +simple("${in.header.date} == ${date:now:yyyyMMdd}") + +simple("${in.header.type} == ${bean:orderService?method=getOrderType}") +---- + +And an example with contains, testing if the title contains the word +Camel + +[source,java] +---- +simple("${in.header.title} contains 'Camel'") +---- + +And an example with regex, testing if the number header is a 4 digit +value: + +[source,java] +---- +simple("${in.header.number} regex '\\d{4}'") +---- + +And finally an example if the header equals any of the values in the +list. Each element must be separated by comma, and no space around. + + This also works for numbers etc, as Camel will convert each element +into the type of the left hand side. + +[source,java] +---- +simple("${in.header.type} in 'gold,silver'") +---- + +And for all the last 3 we also support the negate test using not: + +[source,java] +---- +simple("${in.header.type} !in 'gold,silver'") +---- + +And you can test if the type is a certain instance, eg for instance a +String + +[source,java] +---- +simple("${in.header.type} is 'java.lang.String'") +---- + +We have added a shorthand for all `java.lang` types so you can write it +as: + +[source,java] +---- +simple("${in.header.type} is 'String'") +---- + +Ranges are also supported. The range interval requires numbers and both +from and end are inclusive. For instance to test whether a value is +between 100 and 199: + +[source,java] +---- +simple("${in.header.number} range 100..199") +---- + +Notice we use `..` in the range without spaces. It is based on the same +syntax as Groovy. + +From *Camel 2.9* onwards the range value must be in single quotes + +[source,java] +---- +simple("${in.header.number} range '100..199'") +---- + +==== Using Spring XML + +As the Spring XML does not have all the power as the Java DSL with all +its various builder methods, you have to resort to use some other +languages for testing with simple operators. Now you can do this with the simple +language. In the sample below we want to test if the header is a widget +order: + +[source,xml] +---- +<from uri="seda:orders"> + <filter> + <simple>${in.header.type} == 'widget'</simple> + <to uri="bean:orderService?method=handleWidget"/> + </filter> +</from> +---- + +=== Using and / or + +If you have two expressions you can combine them with the `&&` or `||` +operator. + +For instance: + +[source,java] +----- +simple("${in.header.title} contains 'Camel' && ${in.header.type'} == 'gold'") +----- + +And of course the `||` is also supported. The sample would be: + +[source,java] +----- +simple("${in.header.title} contains 'Camel' || ${in.header.type'} == 'gold'") +----- + +*Notice:* Currently `&&` or `||` can only be used *once* in a simple +language expression. This might change in the future. + + So you *cannot* do: + +[source,java] +----- +simple("${in.header.title} contains 'Camel' && ${in.header.type'} == 'gold' && ${in.header.number} range 100..200") +----- + + +=== Samples + +In the Spring XML sample below we filter based on a header value: + +[source,xml] +-------------------------------------------- +<from uri="seda:orders"> + <filter> + <simple>${in.header.foo}</simple> + <to uri="mock:fooOrders"/> + </filter> +</from> +-------------------------------------------- + +The Simple language can be used for the predicate test above in the +Message Filter pattern, where we test if the +in message has a `foo` header (a header with the key `foo` exists). If +the expression evaluates to *true* then the message is routed to the +`mock:fooOrders` endpoint, otherwise the message is dropped. + +The same example in Java DSL: + +[source,java] +---- +from("seda:orders") + .filter().simple("${in.header.foo}") + .to("seda:fooOrders"); +---- + +You can also use the simple language for simple text concatenations such +as: + +[source,java] +---- +from("direct:hello") + .transform().simple("Hello ${in.header.user} how are you?") + .to("mock:reply"); +---- + +Notice that we must use $\{ } placeholders in the expression now to +allow Camel to parse it correctly. + +And this sample uses the date command to output current date. + +[source,java] +---- +from("direct:hello") + .transform().simple("The today is ${date:now:yyyyMMdd} and it is a great day.") + .to("mock:reply"); +---- + +And in the sample below we invoke the bean language to invoke a method +on a bean to be included in the returned string: + +[source,java] +---- +from("direct:order") + .transform().simple("OrderId: ${bean:orderIdGenerator}") + .to("mock:reply"); +---- + +Where `orderIdGenerator` is the id of the bean registered in the +Registry. If using Spring then it is the Spring bean +id. + +If we want to declare which method to invoke on the order id generator +bean we must prepend `.method name` such as below where we invoke the +`generateId` method. + +[source,java] +---- +from("direct:order") + .transform().simple("OrderId: ${bean:orderIdGenerator.generateId}") + .to("mock:reply"); +---- + +We can use the `?method=methodname` option that we are familiar with the +<<bean-component,Bean>> component itself: + +[source,java] +---- +from("direct:order") + .transform().simple("OrderId: ${bean:orderIdGenerator?method=generateId}") + .to("mock:reply"); +---- + +And from Camel 2.3 onwards you can also convert the body to a given +type, for example to ensure that it is a String you can do: + +[source,xml] +---- +<transform> + <simple>Hello ${bodyAs(String)} how are you?</simple> +</transform> +---- + +There are a few types which have a shorthand notation, so we can use +`String` instead of `java.lang.String`. These are: +`byte[], String, Integer, Long`. All other types must use their FQN +name, e.g. `org.w3c.dom.Document`. + +It is also possible to lookup a value from a header `Map` in *Camel 2.3* +onwards: + +[source,xml] +---- +<transform> + <simple>The gold value is ${header.type[gold]}</simple> +</transform> +---- + +In the code above we lookup the header with name `type` and regard it as +a `java.util.Map` and we then lookup with the key `gold` and return the +value. If the header is not convertible to Map an exception is thrown. If the +header with name `type` does not exist `null` is returned. + +From Camel 2.9 onwards you can nest functions, such as shown below: + +[source,xml] +---- +<setHeader headerName="myHeader"> + <simple>${properties:${header.someKey}}</simple> +</setHeader> +---- + +=== Referring to constants or enums + +Suppose you have an enum for customers + +And in a Content Based Router we can use +the <<simple-language,Simple>> language to refer to this enum, to check +the message which enum it matches. + +=== Using new lines or tabs in XML DSLs + +From Camel 2.9.3 onwards it is easier to specify new lines or tabs in +XML DSLs as you can escape the value now + +[source,xml] +---- +<transform> + <simple>The following text\nis on a new line</simple> +</transform> +---- + +=== Leading and trailing whitespace handling + +The trim attribute of the expression can be +used to control whether the leading and trailing whitespace characters +are removed or preserved. The default value is true, which removes the +whitespace characters. + +[source,xml] +---- +<setBody> + <simple trim="false">You get some trailing whitespace characters. </simple> +</setBody> +---- + +=== Setting result type + +You can now provide a result type to the <<simple-language,Simple>> +expression, which means the result of the evaluation will be converted +to the desired type. This is most useable to define types such as +booleans, integers, etc. + +For example to set a header as a boolean type you can do: + +[source,java] +---- +.setHeader("cool", simple("true", Boolean.class)) +---- + +And in XML DSL + +[source,xml] +---- +<setHeader headerName="cool"> + <!-- use resultType to indicate that the type should be a java.lang.Boolean --> + <simple resultType="java.lang.Boolean">true</simple> +</setHeader> +---- + +=== Loading script from external resource + +You can externalize the script and have Camel load it from a resource +such as `"classpath:"`, `"file:"`, or `"http:"`. + + This is done using the following syntax: `"resource:scheme:location"`, +eg to refer to a file on the classpath you can do: + +[source,java] +---- +.setHeader("myHeader").simple("resource:classpath:mysimple.txt") +---- + +=== Setting Spring beans to Exchange properties + +You can set a spring bean into an exchange property as shown below: + +[source,xml] +---- +<bean id="myBeanId" class="my.package.MyCustomClass" /> +... +<route> + ... + <setProperty propertyName="monitoring.message"> + <simple>ref:myBeanId</simple> + </setProperty> + ... +</route> +---- + diff --git a/core/camel-base/src/main/docs/tokenize-language.adoc b/core/camel-base/src/main/docs/tokenize-language.adoc new file mode 100644 index 0000000..63937d7 --- /dev/null +++ b/core/camel-base/src/main/docs/tokenize-language.adoc @@ -0,0 +1,38 @@ +[[tokenize-language]] +== Tokenize Language + +*Available as of Camel version 2.0* + +The tokenizer language is a built-in language in camel-core, which is +most often used only with the Splitter EIP to split +a message using a token-based strategy. + +The tokenizer language is intended to tokenize text documents using a +specified delimiter pattern. It can also be used to tokenize XML +documents with some limited capability. For a truly XML-aware +tokenization, the use of the XMLTokenizer +language is recommended as it offers a faster, more efficient +tokenization specifically for XML documents. For more details +see Splitter. + +=== Tokenize Options + +// language options: START +The Tokenize language supports 10 options, which are listed below. + + + +[width="100%",cols="2,1m,1m,6",options="header"] +|=== +| Name | Default | Java Type | Description +| token | | String | The (start) token to use as tokenizer, for example you can use the new line token. You can use simple language as the token to support dynamic tokens. +| endToken | | String | The end token to use as tokenizer if using start/end token pairs. You can use simple language as the token to support dynamic tokens. +| inheritNamespaceTagName | | String | To inherit namespaces from a root/parent tag name when using XML You can use simple language as the tag name to support dynamic names. +| headerName | | String | Name of header to tokenize instead of using the message body. +| regex | false | Boolean | If the token is a regular expression pattern. The default value is false +| xml | false | Boolean | Whether the input is XML messages. This option must be set to true if working with XML payloads. +| includeTokens | false | Boolean | Whether to include the tokens in the parts when using pairs The default value is false +| group | | String | To group N parts together, for example to split big files into chunks of 1000 lines. You can use simple language as the group to support dynamic group sizes. +| skipFirst | false | Boolean | To skip the very first element +| trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks +|=== +// language options: END