This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch 13557 in repository https://gitbox.apache.org/repos/asf/camel.git
commit e4a1168aa27dabb73ed7a85a829f3a616116c87b Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Thu May 23 07:15:32 2019 +0200 CAMEL-13557: Add property binding support to make it convenient to configure components and whatnot. --- .../java/org/apache/camel/support/Company.java | 38 ++++++++++++++ .../camel/support/PropertyBindingSupportTest.java | 58 ++++++++++++++-------- .../camel/support/PropertyBindingSupport.java | 38 +++++++++++--- 3 files changed, 106 insertions(+), 28 deletions(-) diff --git a/core/camel-core/src/test/java/org/apache/camel/support/Company.java b/core/camel-core/src/test/java/org/apache/camel/support/Company.java new file mode 100644 index 0000000..1f5caba --- /dev/null +++ b/core/camel-core/src/test/java/org/apache/camel/support/Company.java @@ -0,0 +1,38 @@ +/* + * 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.support; + +public class Company { + private int id; + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java index 3f28037..e6e4245 100644 --- a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java @@ -105,6 +105,43 @@ public class PropertyBindingSupportTest extends ContextTestSupport { assertEquals("Acme", foo.getBar().getWork().getName()); } + @Test + public void testNestedType() throws Exception { + Foo foo = new Foo(); + + PropertyBindingSupport.bindProperty(context, foo, "name", "James"); + PropertyBindingSupport.bindProperty(context, foo, "bar.age", "33"); + PropertyBindingSupport.bindProperty(context, foo, "bar.{{committer}}", "true"); + PropertyBindingSupport.bindProperty(context, foo, "bar.gold-customer", "true"); + PropertyBindingSupport.bindProperty(context, foo, "bar.work", "#type:org.apache.camel.support.Company"); + + assertEquals("James", foo.getName()); + assertEquals(33, foo.getBar().getAge()); + assertTrue(foo.getBar().isRider()); + assertTrue(foo.getBar().isGoldCustomer()); + assertEquals(456, foo.getBar().getWork().getId()); + assertEquals("Acme", foo.getBar().getWork().getName()); + } + + @Test + public void testNestedClass() throws Exception { + Foo foo = new Foo(); + + PropertyBindingSupport.bindProperty(context, foo, "name", "James"); + PropertyBindingSupport.bindProperty(context, foo, "bar.age", "33"); + PropertyBindingSupport.bindProperty(context, foo, "bar.{{committer}}", "true"); + PropertyBindingSupport.bindProperty(context, foo, "bar.gold-customer", "true"); + PropertyBindingSupport.bindProperty(context, foo, "bar.work", "class:org.apache.camel.support.Company"); + + assertEquals("James", foo.getName()); + assertEquals(33, foo.getBar().getAge()); + assertTrue(foo.getBar().isRider()); + assertTrue(foo.getBar().isGoldCustomer()); + // a new class was created so its empty + assertEquals(0, foo.getBar().getWork().getId()); + assertEquals(null, foo.getBar().getWork().getName()); + } + public static class Foo { private String name; private Bar bar = new Bar(); @@ -165,26 +202,5 @@ public class PropertyBindingSupportTest extends ContextTestSupport { } } - public static class Company { - private int id; - private String name; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java index d9bfb03..1577b14 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java @@ -33,12 +33,15 @@ import static org.apache.camel.support.IntrospectionSupport.getOrElseProperty; * <li>property placeholders - Keys and values using Camels property placeholder will be resolved</li> * <li>nested - Properties can be nested using the dot syntax (OGNL and builder pattern using with as prefix), eg foo.bar=123</li> * <li>reference by id - Values can refer to other beans in the registry by prefixing with # syntax, eg #myBean</li> + * <li>reference by type - Values can refer to singleton beans by their type in the registry by prefixing with #type: syntax, eg #type:com.foo.MyClassType</li> + * <li>new class - Values can refer to creating new beans by their class name syntax, eg class:com.foo.MyClassType</li> * </ul> * This implementations reuses parts of {@link IntrospectionSupport}. */ public final class PropertyBindingSupport { // TODO: Add support for auto binding to singleton instance by type from registry (boolean on|off) + // TODO: Better exception message if something goes wrong (output target, name of property etc) private PropertyBindingSupport() { } @@ -117,14 +120,35 @@ public final class PropertyBindingSupport { } } // okay we found a nested property, then lets change to use that - target = newTarget; - name = parts[parts.length - 1]; - if (value instanceof String) { - if (EndpointHelper.isReferenceParameter(value.toString())) { - // okay its a reference so swap to lookup this - refName = value.toString(); - value = null; + try { + target = newTarget; + name = parts[parts.length - 1]; + if (value instanceof String) { + if (value.toString().startsWith("class:")) { + // its a new class to be created + String className = value.toString().substring(6); + Class<?> type = context.getClassResolver().resolveMandatoryClass(className); + if (type != null) { + value = context.getInjector().newInstance(type); + } + } else if (value.toString().startsWith("#type:")) { + // its reference by type, so lookup the actual value and use it if there is only one instance in the registry + String typeName = value.toString().substring(6); + Class<?> type = context.getClassResolver().resolveMandatoryClass(typeName); + if (type != null) { + Set<?> types = context.getRegistry().findByType(type); + if (types.size() == 1) { + value = types.iterator().next(); + } + } + } else if (EndpointHelper.isReferenceParameter(value.toString())) { + // okay its a reference so swap to lookup this which is already supported in IntrospectionSupport + refName = value.toString(); + value = null; + } } + } catch (Exception e) { + throw RuntimeCamelException.wrapRuntimeException(e); } }