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 bca543923733727898c02954ee09f7acb8bab389 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Tue May 19 21:17:23 2020 +0200 endpointdsl - Fix multivalue when using Map as parameter --- .../camel/builder/EndpointConsumerBuilder.java | 8 ++ .../camel/builder/EndpointProducerBuilder.java | 8 ++ .../builder/endpoint/AbstractEndpointBuilder.java | 6 ++ .../builder/endpoint/RabbitMQMultiValueTest.java | 34 ++++++++ .../camel/maven/packaging/EndpointDslMojo.java | 93 ++++++++++------------ 5 files changed, 99 insertions(+), 50 deletions(-) diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/builder/EndpointConsumerBuilder.java b/core/camel-core-engine/src/main/java/org/apache/camel/builder/EndpointConsumerBuilder.java index 88d34fd..fe264e7 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/builder/EndpointConsumerBuilder.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/builder/EndpointConsumerBuilder.java @@ -16,6 +16,8 @@ */ package org.apache.camel.builder; +import java.util.Map; + import org.apache.camel.EndpointConsumerResolver; /** @@ -42,4 +44,10 @@ public interface EndpointConsumerBuilder extends EndpointConsumerResolver { */ void doSetMultiValueProperty(String name, String key, Object value); + /** + * Adds multi-value options to this endpoint. This API is only intended for Camel + * internally. + */ + void doSetMultiValueProperties(String name, String prefix, Map<String, Object> values); + } diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/builder/EndpointProducerBuilder.java b/core/camel-core-engine/src/main/java/org/apache/camel/builder/EndpointProducerBuilder.java index 5fa60f7..f9d2a4f 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/builder/EndpointProducerBuilder.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/builder/EndpointProducerBuilder.java @@ -16,6 +16,8 @@ */ package org.apache.camel.builder; +import java.util.Map; + import org.apache.camel.CamelContext; import org.apache.camel.EndpointProducerResolver; import org.apache.camel.Expression; @@ -45,6 +47,12 @@ public interface EndpointProducerBuilder extends EndpointProducerResolver { void doSetMultiValueProperty(String name, String key, Object value); /** + * Adds multi-value options to this endpoint. This API is only intended for Camel + * internally. + */ + void doSetMultiValueProperties(String name, String prefix, Map<String, Object> values); + + /** * Builds an expression of this endpoint url. This API is only intended for * Camel internally. */ diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/AbstractEndpointBuilder.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/AbstractEndpointBuilder.java index 3095568..90ffc0f 100644 --- a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/AbstractEndpointBuilder.java +++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/AbstractEndpointBuilder.java @@ -146,6 +146,12 @@ public class AbstractEndpointBuilder { map.put(key, value); } + public void doSetMultiValueProperties(String name, String prefix, Map<String, Object> values) { + values.forEach((k, v) -> { + doSetMultiValueProperty(name, prefix + k, v); + }); + } + public Expression expr() { return SimpleBuilder.simple(getUri()); } diff --git a/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/RabbitMQMultiValueTest.java b/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/RabbitMQMultiValueTest.java index 93edc4e..573320c 100644 --- a/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/RabbitMQMultiValueTest.java +++ b/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/RabbitMQMultiValueTest.java @@ -16,6 +16,7 @@ */ package org.apache.camel.builder.endpoint; +import java.util.HashMap; import java.util.Map; import org.apache.camel.ContextTestSupport; @@ -61,4 +62,37 @@ public class RabbitMQMultiValueTest extends ContextTestSupport { context.stop(); } + @Test + public void testMultiValueMap() throws Exception { + context.start(); + + context.addRoutes(new EndpointRouteBuilder() { + @Override + public void configure() throws Exception { + Map map = new HashMap(); + map.put("foo", "123"); + map.put("bar", "456"); + map.put("beer", "yes"); + + RabbitMQEndpointBuilderFactory.RabbitMQEndpointBuilder builder = + rabbitmq("mytopic").advanced() + .args(map).basic(); + + Endpoint endpoint = builder.resolve(context); + assertNotNull(endpoint); + assertEquals("rabbitmq://mytopic?arg.bar=456&arg.beer=yes&arg.foo=123", endpoint.getEndpointUri()); + RabbitMQEndpoint re = assertIsInstanceOf(RabbitMQEndpoint.class, endpoint); + assertEquals("mytopic", re.getExchangeName()); + Map<String, Object> args = re.getArgs(); + assertNotNull(args); + assertEquals(3, args.size()); + assertEquals("123", args.get("foo")); + assertEquals("456", args.get("bar")); + assertEquals("yes", args.get("beer")); + } + }); + + context.stop(); + } + } diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointDslMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointDslMojo.java index 011cc08..4e12fd9 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointDslMojo.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointDslMojo.java @@ -421,80 +421,73 @@ public class EndpointDslMojo extends AbstractGeneratorMojo { if (target == null) { continue; } - Method fluent = target.addMethod().setDefault().setName(option.getName()).setReturnType(new GenericType(loadClass(target.getCanonicalName()))) - .addParameter(isPrimitive(ogtype.toString()) ? ogtype : gtype, option.getName()) - .setBody("doSetProperty(\"" + option.getName() + "\", " + option.getName() + ");", "return this;\n"); - if (option.isDeprecated()) { - fluent.addAnnotation(Deprecated.class); - } - if (!Strings.isEmpty(option.getDescription())) { - String desc = option.getDescription(); - if (!desc.endsWith(".")) { - desc += "."; + // basic description + String baseDesc = option.getDescription(); + if (!Strings.isEmpty(baseDesc)) { + if (!baseDesc.endsWith(".")) { + baseDesc += "."; } - desc += "\n"; - desc += "\nThe option is a: <code>" + ogtype.toString().replace("<", "<").replace(">", ">") + "</code> type."; + baseDesc += "\n"; + baseDesc += "@@REPLACE_ME@@"; if (option.isMultiValue()) { - desc += "\nThe option is multivalued, and you can use the " + option.getName() + "(String, Object) method to add a value at a time."; + baseDesc += "\nThe option is multivalued, and you can use the " + option.getName() + + "(String, Object) method to add a value (call the method multiple times to set more values)."; } - desc += "\n"; + baseDesc += "\n"; // the Endpoint DSL currently requires to provide the entire // context-path and not as individual options // so lets only mark query parameters that are required as // required if ("parameter".equals(option.getKind()) && option.isRequired()) { - desc += "\nRequired: true"; + baseDesc += "\nRequired: true"; } // include default value (if any) if (option.getDefaultValue() != null) { - desc += "\nDefault: " + option.getDefaultValue(); + baseDesc += "\nDefault: " + option.getDefaultValue(); } - desc += "\nGroup: " + option.getGroup(); - fluent.getJavaDoc().setFullText(desc); + baseDesc += "\nGroup: " + option.getGroup(); } - // is it multi valued then add method to see value at a time - if (option.isMultiValue()) { - String desc = fluent.getJavaDoc().getFullText(); - fluent = target.addMethod().setDefault().setName(option.getName()).setReturnType(new GenericType(loadClass(target.getCanonicalName()))) + boolean multiValued = option.isMultiValue(); + if (multiValued) { + // multi value option that takes one value + String desc = baseDesc.replace("@@REPLACE_ME@@", "\nThe option is a: <code>" + ogtype.toString().replace("<", "<").replace(">", ">") + "</code> type."); + Method fluent = target.addMethod().setDefault().setName(option.getName()).setReturnType(new GenericType(loadClass(target.getCanonicalName()))) .addParameter(new GenericType(String.class), "key") .addParameter(new GenericType(Object.class), "value") .setBody("doSetMultiValueProperty(\"" + option.getName() + "\", \"" + option.getPrefix() + "\" + key, value);", "return this;\n"); + if (option.isDeprecated()) { + fluent.addAnnotation(Deprecated.class); + } fluent.getJavaDoc().setFullText(desc); - } - - if (ogtype.getRawClass() != String.class) { + // add multi value method that takes a Map fluent = target.addMethod().setDefault().setName(option.getName()).setReturnType(new GenericType(loadClass(target.getCanonicalName()))) - .addParameter(new GenericType(String.class), option.getName()) - .setBody("doSetProperty(\"" + option.getName() + "\", " + option.getName() + ");", "return this;\n"); - + .addParameter(new GenericType(Map.class), "values") + .setBody("doSetMultiValueProperties(\"" + option.getName() + "\", \"" + option.getPrefix() + "\", values);", "return this;\n"); if (option.isDeprecated()) { fluent.addAnnotation(Deprecated.class); } - if (!Strings.isEmpty(option.getDescription())) { - String desc = option.getDescription(); - if (!desc.endsWith(".")) { - desc += "."; - } - desc += "\n"; - desc += "\nThe option will be converted to a <code>" + ogtype.toString().replace("<", "<").replace(">", ">") + "</code> type."; - if (option.isMultiValue()) { - desc += "\nThe option is multivalued, and you can use the " + option.getName() + "(String, Object) method to add a value at a time."; - } - desc += "\n"; - // the Endpoint DSL currently requires to provide the - // entire context-path and not as individual options - // so lets only mark query parameters that are required - // as required - if ("parameter".equals(option.getKind()) && option.isRequired()) { - desc += "\nRequired: true"; - } - // include default value (if any) - if (option.getDefaultValue() != null) { - desc += "\nDefault: " + option.getDefaultValue(); + fluent.getJavaDoc().setFullText(desc); + } else { + // regular option + String desc = baseDesc.replace("@@REPLACE_ME@@", "\nThe option is a: <code>" + ogtype.toString().replace("<", "<").replace(">", ">") + "</code> type."); + Method fluent = target.addMethod().setDefault().setName(option.getName()).setReturnType(new GenericType(loadClass(target.getCanonicalName()))) + .addParameter(isPrimitive(ogtype.toString()) ? ogtype : gtype, option.getName()) + .setBody("doSetProperty(\"" + option.getName() + "\", " + option.getName() + ");", "return this;\n"); + if (option.isDeprecated()) { + fluent.addAnnotation(Deprecated.class); + } + fluent.getJavaDoc().setFullText(desc); + if (ogtype.getRawClass() != String.class) { + // regular option by String parameter variant + desc = baseDesc.replace("@@REPLACE_ME@@", "\nThe option will be converted to a <code>" + ogtype.toString().replace("<", "<").replace(">", ">") + "</code> type."); + fluent = target.addMethod().setDefault().setName(option.getName()).setReturnType(new GenericType(loadClass(target.getCanonicalName()))) + .addParameter(new GenericType(String.class), option.getName()) + .setBody("doSetProperty(\"" + option.getName() + "\", " + option.getName() + ");", "return this;\n"); + if (option.isDeprecated()) { + fluent.addAnnotation(Deprecated.class); } - desc += "\nGroup: " + option.getGroup(); fluent.getJavaDoc().setFullText(desc); } }