This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel.git
commit 7d07d3ba7ddbede6b8fff54034dcc2197096da0c Author: Claus Ibsen <[email protected]> AuthorDate: Thu Oct 1 15:27:57 2020 +0200 CAMEL-15605: Languages should be singleton for better performance. --- .../camel/catalog/docs/jsonpath-language.adoc | 3 +- .../apache/camel/language/bean/BeanExpression.java | 16 ---- .../apache/camel/language/bean/BeanLanguage.java | 45 +++++++++++ .../org/apache/camel/jsonpath/jsonpath.json | 1 + .../src/main/docs/jsonpath-language.adoc | 3 +- .../apache/camel/jsonpath/JsonPathExpression.java | 40 +--------- .../apache/camel/jsonpath/JsonPathLanguage.java | 92 ++++++++++++++++++---- .../camel/jsonpath/JsonPathLanguageTest.java | 2 +- .../main/java/org/apache/camel/spi/Language.java | 8 +- .../org/apache/camel/model/language/jsonpath.json | 1 + .../camel/model/language/JsonPathExpression.java | 14 ++++ .../language/JsonPathExpressionReifier.java | 42 ++++++---- .../org/apache/camel/support/LanguageSupport.java | 72 +++++++++++++++++ .../java/org/apache/camel/xml/in/ModelParser.java | 1 + .../modules/languages/pages/jsonpath-language.adoc | 3 +- 15 files changed, 250 insertions(+), 93 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jsonpath-language.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jsonpath-language.adoc index 806aca9..87ae77d 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jsonpath-language.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jsonpath-language.adoc @@ -29,7 +29,7 @@ from("queue:books.new") // language options: START -The JsonPath language supports 7 options, which are listed below. +The JsonPath language supports 8 options, which are listed below. @@ -42,6 +42,7 @@ The JsonPath language supports 7 options, which are listed below. | allowEasyPredicate | true | Boolean | Whether to allow using the easy predicate parser to pre-parse predicates. | writeAsString | false | Boolean | Whether to write the output of each row/element as a JSON String value instead of a Map/POJO value. | headerName | | String | Name of header to use as input, instead of the message body +| option | | String | To configure additional options on json path. Multiple values can be separated by comma. | trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks |=== // language options: END diff --git a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java index 6fdaafa..9d2038e 100644 --- a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java +++ b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java @@ -81,34 +81,18 @@ public class BeanExpression implements Expression, Predicate, AfterPropertiesCon return bean; } - public void setBean(Object bean) { - this.bean = bean; - } - public String getBeanName() { return beanName; } - public void setBeanName(String beanName) { - this.beanName = beanName; - } - public Class<?> getType() { return type; } - public void setType(Class<?> type) { - this.type = type; - } - public String getMethod() { return method; } - public void setMethod(String method) { - this.method = method; - } - @Override public void init(CamelContext context) { } diff --git a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanLanguage.java b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanLanguage.java index 70d6692..d59e676d 100644 --- a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanLanguage.java +++ b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanLanguage.java @@ -38,9 +38,46 @@ import org.apache.camel.util.StringHelper; @org.apache.camel.spi.annotations.Language("bean") public class BeanLanguage extends LanguageSupport { + private Object bean; + private Class<?> beanType; + private String ref; + private String method; + public BeanLanguage() { } + public Object getBean() { + return bean; + } + + public void setBean(Object bean) { + this.bean = bean; + } + + public Class<?> getBeanType() { + return beanType; + } + + public void setBeanType(Class<?> beanType) { + this.beanType = beanType; + } + + public String getRef() { + return ref; + } + + public void setRef(String ref) { + this.ref = ref; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + @Override public Predicate createPredicate(String expression) { return ExpressionToPredicateAdapter.toPredicate(createExpression(expression)); @@ -72,6 +109,14 @@ public class BeanLanguage extends LanguageSupport { @Override public Expression createExpression(String expression) { // favour using the configured options + if (bean != null) { + return new BeanExpression(bean, method); + } else if (beanType != null) { + return new BeanExpression(beanType, method); + } else if (ref != null) { + return new BeanExpression(ref, method); + } + String beanName = expression; String method = null; diff --git a/components/camel-jsonpath/src/generated/resources/org/apache/camel/jsonpath/jsonpath.json b/components/camel-jsonpath/src/generated/resources/org/apache/camel/jsonpath/jsonpath.json index a97e759..c5fab68 100644 --- a/components/camel-jsonpath/src/generated/resources/org/apache/camel/jsonpath/jsonpath.json +++ b/components/camel-jsonpath/src/generated/resources/org/apache/camel/jsonpath/jsonpath.json @@ -23,6 +23,7 @@ "allowEasyPredicate": { "kind": "attribute", "displayName": "Allow Easy Predicate", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "secret": false, "defaultValue": true, "description": "Whether to allow using the easy predicate parser to pre-parse predicates." }, "writeAsString": { "kind": "attribute", "displayName": "Write As String", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "secret": false, "defaultValue": false, "description": "Whether to write the output of each row\/element as a JSON String value instead of a Map\/POJO value." }, "headerName": { "kind": "attribute", "displayName": "Header Name", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "description": "Name of header to use as input, instead of the message body" }, + "option": { "kind": "attribute", "displayName": "Option", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "ALWAYS_RETURN_LIST", "AS_PATH_LIST", "DEFAULT_PATH_LEAF_TO_NULL", "REQUIRE_PROPERTIES", "SUPPRESS_EXCEPTIONS" ], "deprecated": false, "secret": false, "description": "To configure additional options on json path. Multiple values can be separated by comma." }, "trim": { "kind": "attribute", "displayName": "Trim", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "secret": false, "defaultValue": true, "description": "Whether to trim the value to remove leading and trailing whitespaces and line breaks" }, "id": { "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "description": "Sets the id of this node" } } diff --git a/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc b/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc index 806aca9..87ae77d 100644 --- a/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc +++ b/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc @@ -29,7 +29,7 @@ from("queue:books.new") // language options: START -The JsonPath language supports 7 options, which are listed below. +The JsonPath language supports 8 options, which are listed below. @@ -42,6 +42,7 @@ The JsonPath language supports 7 options, which are listed below. | allowEasyPredicate | true | Boolean | Whether to allow using the easy predicate parser to pre-parse predicates. | writeAsString | false | Boolean | Whether to write the output of each row/element as a JSON String value instead of a Map/POJO value. | headerName | | String | Name of header to use as input, instead of the message body +| option | | String | To configure additional options on json path. Multiple values can be separated by comma. | trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks |=== // language options: END diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java index 60954f9..7dfb850 100644 --- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java +++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java @@ -26,13 +26,11 @@ import org.apache.camel.Exchange; import org.apache.camel.ExpressionEvaluationException; import org.apache.camel.ExpressionIllegalSyntaxException; import org.apache.camel.jsonpath.easypredicate.EasyPredicateParser; -import org.apache.camel.spi.GeneratedPropertyConfigurer; import org.apache.camel.support.ExpressionAdapter; -import org.apache.camel.support.component.PropertyConfigurerSupport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class JsonPathExpression extends ExpressionAdapter implements AfterPropertiesConfigured, GeneratedPropertyConfigurer { +public class JsonPathExpression extends ExpressionAdapter implements AfterPropertiesConfigured { private static final Logger LOG = LoggerFactory.getLogger(JsonPathExpression.class); @@ -46,47 +44,13 @@ public class JsonPathExpression extends ExpressionAdapter implements AfterProper private boolean allowEasyPredicate = true; private boolean writeAsString; private String headerName; + private String option; private Option[] options; public JsonPathExpression(String expression) { this.expression = expression; } - @Override - public boolean configure(CamelContext camelContext, Object target, String name, Object value, boolean ignoreCase) { - if (target != this) { - throw new IllegalStateException("Can only configure our own instance !"); - } - switch (ignoreCase ? name.toLowerCase() : name) { - case "resulttype": - case "resultType": - setResultType(PropertyConfigurerSupport.property(camelContext, Class.class, value)); - return true; - case "suppressexceptions": - case "suppressExceptions": - setSuppressExceptions(PropertyConfigurerSupport.property(camelContext, Boolean.class, value)); - return true; - case "allowsimple": - case "allowSimple": - setAllowSimple(PropertyConfigurerSupport.property(camelContext, Boolean.class, value)); - return true; - case "alloweasypredicate": - case "allowEasyPredicate": - setAllowEasyPredicate(PropertyConfigurerSupport.property(camelContext, Boolean.class, value)); - return true; - case "writeasstring": - case "writeAsString": - setWriteAsString(PropertyConfigurerSupport.property(camelContext, Boolean.class, value)); - return true; - case "headername": - case "headerName": - setHeaderName(PropertyConfigurerSupport.property(camelContext, String.class, value)); - return true; - default: - return false; - } - } - public boolean isPredicate() { return predicate; } diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java index 0873981..e04bb94 100644 --- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java +++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java @@ -16,6 +16,10 @@ */ package org.apache.camel.jsonpath; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + import com.jayway.jsonpath.Option; import org.apache.camel.Expression; import org.apache.camel.Predicate; @@ -27,6 +31,10 @@ public class JsonPathLanguage extends LanguageSupport { private Class<?> resultType; private boolean suppressExceptions; + private boolean allowSimple = true; + private boolean allowEasyPredicate = true; + private boolean writeAsString; + private String headerName; private Option[] options; public Class<?> getResultType() { @@ -45,43 +53,95 @@ public class JsonPathLanguage extends LanguageSupport { this.suppressExceptions = suppressExceptions; } - public Option[] getOptions() { - return options; + public boolean isAllowSimple() { + return allowSimple; + } + + public void setAllowSimple(boolean allowSimple) { + this.allowSimple = allowSimple; + } + + public boolean isAllowEasyPredicate() { + return allowEasyPredicate; + } + + public void setAllowEasyPredicate(boolean allowEasyPredicate) { + this.allowEasyPredicate = allowEasyPredicate; + } + + public boolean isWriteAsString() { + return writeAsString; + } + + public void setWriteAsString(boolean writeAsString) { + this.writeAsString = writeAsString; + } + + public String getHeaderName() { + return headerName; } - public void setOption(Option option) { - this.options = new Option[] { option }; + public void setHeaderName(String headerName) { + this.headerName = headerName; } - public void setOptions(Option[] options) { + public Option[] getOptions() { + return options; + } + + public void setOptions(Option... options) { this.options = options; } @Override - public Predicate createPredicate(final String predicate) { - JsonPathExpression answer = new JsonPathExpression(predicate); + public Predicate createPredicate(String expression) { + JsonPathExpression answer = (JsonPathExpression) createExpression(expression); answer.setPredicate(true); - answer.setResultType(resultType); - answer.setSuppressExceptions(suppressExceptions); - answer.setOptions(options); - answer.afterPropertiesConfigured(getCamelContext()); return answer; } @Override - public Expression createExpression(final String expression) { + public Expression createExpression(String expression) { JsonPathExpression answer = new JsonPathExpression(expression); - answer.setPredicate(false); answer.setResultType(resultType); answer.setSuppressExceptions(suppressExceptions); + answer.setAllowSimple(allowSimple); + answer.setAllowEasyPredicate(allowEasyPredicate); + answer.setHeaderName(headerName); + answer.setWriteAsString(writeAsString); + answer.setHeaderName(headerName); answer.setOptions(options); answer.afterPropertiesConfigured(getCamelContext()); return answer; } @Override - public boolean isSingleton() { - // cannot be singleton due options - return false; + public Predicate createPredicate(Map<String, Object> properties) { + JsonPathExpression json = (JsonPathExpression) createExpression(properties); + json.setPredicate(true); + return json; } + + @Override + public Expression createExpression(Map<String, Object> properties) { + String exp = (String) properties.get("expression"); + JsonPathExpression answer = new JsonPathExpression(exp); + answer.setResultType(property(Class.class, properties, "resultType", null)); + answer.setSuppressExceptions(property(boolean.class, properties, "suppressExceptions", true)); + answer.setAllowEasyPredicate(property(boolean.class, properties, "allowEasyPredicate", true)); + answer.setAllowSimple(property(boolean.class, properties, "allowSimple", true)); + answer.setWriteAsString(property(boolean.class, properties, "writeAsString", false)); + answer.setHeaderName(property(String.class, properties, "headerName", null)); + String option = (String) properties.get("option"); + if (option != null) { + List<Option> list = new ArrayList<>(); + for (String s : option.split(",")) { + list.add(getCamelContext().getTypeConverter().convertTo(Option.class, s)); + } + answer.setOptions(list.toArray(new Option[list.size()])); + } + answer.afterPropertiesConfigured(getCamelContext()); + return answer; + } + } diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathLanguageTest.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathLanguageTest.java index 7f9769f..e6bea51 100644 --- a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathLanguageTest.java +++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathLanguageTest.java @@ -128,7 +128,7 @@ public class JsonPathLanguageTest extends CamelTestSupport { exchange.getIn().setBody(new File("src/test/resources/type.json")); JsonPathLanguage lan = (JsonPathLanguage) context.resolveLanguage("jsonpath"); - lan.setOption(Option.SUPPRESS_EXCEPTIONS); + lan.setOptions(Option.SUPPRESS_EXCEPTIONS); Expression exp = lan.createExpression("$.foo"); String nofoo = exp.evaluate(exchange, String.class); diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/Language.java b/core/camel-api/src/main/java/org/apache/camel/spi/Language.java index 1376c76..b046242 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/Language.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/Language.java @@ -45,8 +45,8 @@ public interface Language { /** * Creates an expression based on the given inputs properties * - * This is used for languages that have been configured with custom properties - * most noticeable for xpath/xquery/tokenizer languages that have several options. + * This is used for languages that have been configured with custom properties most noticeable for + * xpath/xquery/tokenizer languages that have several options. * * @param properties arguments * @return the created predicate @@ -58,8 +58,8 @@ public interface Language { /** * Creates an expression based on the given inputs properties * - * This is used for languages that have been configured with custom properties - * most noticeable for xpath/xquery/tokenizer languages that have several options. + * This is used for languages that have been configured with custom properties most noticeable for + * xpath/xquery/tokenizer languages that have several options. * * @param properties arguments * @return the created expression diff --git a/core/camel-core-engine/src/generated/resources/org/apache/camel/model/language/jsonpath.json b/core/camel-core-engine/src/generated/resources/org/apache/camel/model/language/jsonpath.json index 532aef0..d30d808 100644 --- a/core/camel-core-engine/src/generated/resources/org/apache/camel/model/language/jsonpath.json +++ b/core/camel-core-engine/src/generated/resources/org/apache/camel/model/language/jsonpath.json @@ -19,6 +19,7 @@ "allowEasyPredicate": { "kind": "attribute", "displayName": "Allow Easy Predicate", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "secret": false, "defaultValue": true, "description": "Whether to allow using the easy predicate parser to pre-parse predicates." }, "writeAsString": { "kind": "attribute", "displayName": "Write As String", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "secret": false, "defaultValue": false, "description": "Whether to write the output of each row\/element as a JSON String value instead of a Map\/POJO value." }, "headerName": { "kind": "attribute", "displayName": "Header Name", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "description": "Name of header to use as input, instead of the message body" }, + "option": { "kind": "attribute", "displayName": "Option", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "ALWAYS_RETURN_LIST", "AS_PATH_LIST", "DEFAULT_PATH_LEAF_TO_NULL", "REQUIRE_PROPERTIES", "SUPPRESS_EXCEPTIONS" ], "deprecated": false, "secret": false, "description": "To configure additional options on json path. Multiple values can be separated by comma." }, "trim": { "kind": "attribute", "displayName": "Trim", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "secret": false, "defaultValue": true, "description": "Whether to trim the value to remove leading and trailing whitespaces and line breaks" }, "id": { "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "description": "Sets the id of this node" } } diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/model/language/JsonPathExpression.java b/core/camel-core-engine/src/main/java/org/apache/camel/model/language/JsonPathExpression.java index 81947b4..732b24f 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/model/language/JsonPathExpression.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/model/language/JsonPathExpression.java @@ -50,6 +50,9 @@ public class JsonPathExpression extends ExpressionDefinition { private String writeAsString; @XmlAttribute private String headerName; + @XmlAttribute + @Metadata(enums = "DEFAULT_PATH_LEAF_TO_NULL,ALWAYS_RETURN_LIST,AS_PATH_LIST,SUPPRESS_EXCEPTIONS,REQUIRE_PROPERTIES") + private String option; public JsonPathExpression() { } @@ -135,6 +138,17 @@ public class JsonPathExpression extends ExpressionDefinition { this.headerName = headerName; } + public String getOption() { + return option; + } + + /** + * To configure additional options on json path. Multiple values can be separated by comma. + */ + public void setOption(String option) { + this.option = option; + } + @Override public String getLanguage() { return "jsonpath"; diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/JsonPathExpressionReifier.java b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/JsonPathExpressionReifier.java index 669386d..b04303e 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/JsonPathExpressionReifier.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/JsonPathExpressionReifier.java @@ -22,38 +22,50 @@ import java.util.Map; import org.apache.camel.CamelContext; import org.apache.camel.Expression; import org.apache.camel.Predicate; +import org.apache.camel.RuntimeCamelException; import org.apache.camel.model.language.ExpressionDefinition; import org.apache.camel.model.language.JsonPathExpression; +import org.apache.camel.spi.Language; public class JsonPathExpressionReifier extends ExpressionReifier<JsonPathExpression> { - // TODO: Update me - public JsonPathExpressionReifier(CamelContext camelContext, ExpressionDefinition definition) { super(camelContext, (JsonPathExpression) definition); } @Override - protected void configureExpression(Expression expression) { - bindProperties(expression); - super.configureExpression(expression); + protected void configureLanguage(Language language) { + if (definition.getResultType() == null && definition.getResultTypeName() != null) { + try { + Class<?> clazz = camelContext.getClassResolver().resolveMandatoryClass(definition.getResultTypeName()); + definition.setResultType(clazz); + } catch (ClassNotFoundException e) { + throw RuntimeCamelException.wrapRuntimeException(e); + } + } } - @Override - protected void configurePredicate(Predicate predicate) { - bindProperties(predicate); - super.configurePredicate(predicate); - } - - private void bindProperties(Object target) { - Map<String, Object> properties = new HashMap<>(); - properties.put("resultType", or(definition.getResultType(), definition.getResultTypeName())); + private Map<String, Object> createProperties(String exp) { + Map<String, Object> properties = new HashMap<>(8); + properties.put("expression", exp); + properties.put("resultType", definition.getResultType()); properties.put("suppressExceptions", definition.getSuppressExceptions()); properties.put("allowSimple", definition.getAllowSimple()); properties.put("allowEasyPredicate", definition.getAllowEasyPredicate()); properties.put("writeAsString", definition.getWriteAsString()); properties.put("headerName", definition.getHeaderName()); - setProperties(target, properties); + properties.put("option", definition.getOption()); + return properties; + } + + @Override + protected Expression createExpression(Language language, String exp) { + return language.createExpression(createProperties(exp)); + } + + @Override + protected Predicate createPredicate(Language language, String exp) { + return language.createPredicate(createProperties(exp)); } } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/LanguageSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/LanguageSupport.java index e762093..6bd6c12 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/LanguageSupport.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/LanguageSupport.java @@ -17,13 +17,17 @@ package org.apache.camel.support; import java.io.InputStream; +import java.util.List; +import java.util.Map; import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.ExpressionIllegalSyntaxException; import org.apache.camel.IsSingleton; +import org.apache.camel.NoSuchBeanException; import org.apache.camel.spi.Language; import org.apache.camel.util.IOHelper; +import org.apache.camel.util.TimeUtils; /** * Base language for {@link Language} implementations. @@ -91,4 +95,72 @@ public abstract class LanguageSupport implements Language, IsSingleton, CamelCon return false; } + /** + * Converts the property to the expected type + * + * @param type the expected type + * @param properties the options + * @param key name of the property + * @param defaultValue optional default value + * @return the value converted to the expected type + */ + protected <T> T property(Class<T> type, Map<String, Object> properties, String key, Object defaultValue) { + Object value = properties.get(key); + if (value == null) { + value = defaultValue; + } + + // if the type is not string based and the value is a bean reference, then we need to lookup + // the bean from the registry + if (value instanceof String && String.class != type) { + String text = value.toString(); + + if (EndpointHelper.isReferenceParameter(text)) { + Object obj; + // special for a list where we refer to beans which can be either a list or a single element + // so use Object.class as type + if (type == List.class) { + obj = EndpointHelper.resolveReferenceListParameter(camelContext, text, Object.class); + } else { + obj = EndpointHelper.resolveReferenceParameter(camelContext, text, type); + } + if (obj == null) { + // no bean found so throw an exception + throw new NoSuchBeanException(text, type.getName()); + } + value = obj; + } else if (type == long.class || type == Long.class || type == int.class || type == Integer.class) { + Object obj = null; + // string to long/int then it may be a duration where we can convert the value to milli seconds + // it may be a time pattern, such as 5s for 5 seconds = 5000 + try { + long num = TimeUtils.toMilliSeconds(text); + if (type == int.class || type == Integer.class) { + // need to cast to int + obj = (int) num; + } else { + obj = num; + } + } catch (IllegalArgumentException e) { + // ignore + } + if (obj != null) { + value = obj; + } + } + } + + // special for boolean values with string values as we only want to accept "true" or "false" + if ((type == Boolean.class || type == boolean.class) && value instanceof String) { + String text = (String) value; + if (!text.equalsIgnoreCase("true") && !text.equalsIgnoreCase("false")) { + throw new IllegalArgumentException( + "Cannot convert the String value: " + value + " to type: " + type + + " as the value is not true or false"); + } + } + + return camelContext.getTypeConverter().convertTo(type, value); + } + } diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java index 354617f..31cea3a 100644 --- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java +++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java @@ -2350,6 +2350,7 @@ public class ModelParser extends BaseParser { case "allowEasyPredicate": def.setAllowEasyPredicate(val); break; case "allowSimple": def.setAllowSimple(val); break; case "headerName": def.setHeaderName(val); break; + case "option": def.setOption(val); break; case "resultType": def.setResultTypeName(val); break; case "suppressExceptions": def.setSuppressExceptions(val); break; case "writeAsString": def.setWriteAsString(val); break; diff --git a/docs/components/modules/languages/pages/jsonpath-language.adoc b/docs/components/modules/languages/pages/jsonpath-language.adoc index 0e57f87..7bfa539 100644 --- a/docs/components/modules/languages/pages/jsonpath-language.adoc +++ b/docs/components/modules/languages/pages/jsonpath-language.adoc @@ -31,7 +31,7 @@ from("queue:books.new") // language options: START -The JsonPath language supports 7 options, which are listed below. +The JsonPath language supports 8 options, which are listed below. @@ -44,6 +44,7 @@ The JsonPath language supports 7 options, which are listed below. | allowEasyPredicate | true | Boolean | Whether to allow using the easy predicate parser to pre-parse predicates. | writeAsString | false | Boolean | Whether to write the output of each row/element as a JSON String value instead of a Map/POJO value. | headerName | | String | Name of header to use as input, instead of the message body +| option | | String | To configure additional options on json path. Multiple values can be separated by comma. | trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks |=== // language options: END
