You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2019/05/24 06:24:57 UTC

[camel] 01/02: CAMEL-13557: Add property binding support to make it convenient to configure components and whatnot.

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 32d50330351818d13e3fe5cfc0fdae9fc134a6c4
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri May 24 08:00:40 2019 +0200

    CAMEL-13557: Add property binding support to make it convenient to configure components and whatnot.
---
 .../camel/support/PropertyBindingSupport.java      | 57 +++++++++++++++++-----
 1 file changed, 46 insertions(+), 11 deletions(-)

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 14e6a37..79916c9 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
@@ -37,14 +37,13 @@ import static org.apache.camel.support.IntrospectionSupport.getOrElseProperty;
  *     <li>reference by bean id - Values can refer to other beans in the registry by prefixing with #nean: eg #bean: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>autowire by type - Values can refer to singleton beans by auto wiring by setting the value to #autowire</li>
- *     <li>new class - Values can refer to creating new beans by their class name syntax, eg class:com.foo.MyClassType</li>
+ *     <li>reference new class - Values can refer to creating new beans by their class name by prefixing with #class, eg #class:com.foo.MyClassType</li>
  * </ul>
  * This implementations reuses parts of {@link IntrospectionSupport}.
  */
 public final class PropertyBindingSupport {
 
     // TODO: Add support for Map/List
-    // TODO: Add option to turn on|off new class
     // TODO: Add option to turn this binding on|off on component/endpoint level
 
     /**
@@ -53,36 +52,66 @@ public final class PropertyBindingSupport {
     public static class Builder {
 
         private boolean nesting = true;
+        private boolean nestingDeep = true;
         private boolean reference = true;
         private boolean placeholder = true;
         private boolean fluentBuilder = true;
 
+        /**
+         * Whether nesting is in use
+         */
         public Builder withNesting(boolean nesting) {
             this.nesting = nesting;
             return this;
         }
 
+        /**
+         * Whether deep nesting is in use, where Camel will attempt to walk as deep as possible by creating new objects in the OGNL graph if
+         * a property has a setter and the object can be created from a default no-arg constructor.
+         */
+        public Builder withNestingDeep(boolean nestingDeep) {
+            this.nestingDeep = nestingDeep;
+            return this;
+        }
+
+        /**
+         * Whether reference parameter (syntax starts with #) is in use
+         */
         public Builder withReference(boolean reference) {
             this.reference = reference;
             return this;
         }
 
+        /**
+         * Whether to use Camels property placeholder to resolve placeholders on keys and values
+         */
         public Builder withPlaceholder(boolean placeholder) {
             this.placeholder = placeholder;
             return this;
         }
 
+        /**
+         * Whether fluent builder is allowed as a valid getter/setter
+         */
         public Builder withFluentBuilder(boolean fluentBuilder) {
             this.fluentBuilder = fluentBuilder;
             return this;
         }
 
+        /**
+         * Binds the properties to the target object, and removes the property that was bound from properties.
+         *
+         * @param camelContext  the camel context
+         * @param target        the target object
+         * @param properties    the properties where the bound properties will be removed from
+         * @return              true if one or more properties was bound
+         */
         public boolean bind(CamelContext camelContext, Object target, Map<String, Object> properties) {
             org.apache.camel.util.ObjectHelper.notNull(camelContext, "camelContext");
             org.apache.camel.util.ObjectHelper.notNull(target, "target");
             org.apache.camel.util.ObjectHelper.notNull(properties, "properties");
 
-            return bindProperties(camelContext, target, properties, nesting, fluentBuilder, reference, placeholder);
+            return bindProperties(camelContext, target, properties, nesting, nestingDeep, fluentBuilder, reference, placeholder);
         }
 
     }
@@ -189,7 +218,7 @@ public final class PropertyBindingSupport {
      * @return              true if one or more properties was bound
      */
     public static boolean bindProperties(CamelContext camelContext, Object target, Map<String, Object> properties) {
-        return bindProperties(camelContext, target, properties, true, true, true, true);
+        return bindProperties(camelContext, target, properties, true, true, true, true, true);
    }
 
     /**
@@ -199,13 +228,15 @@ public final class PropertyBindingSupport {
      * @param target        the target object
      * @param properties    the properties where the bound properties will be removed from
      * @param nesting       whether nesting is in use
+     * @param nestingDeep   whether deep nesting is in use, where Camel will attempt to walk as deep as possible by creating new objects in the OGNL graph if
+     *                      a property has a setter and the object can be created from a default no-arg constructor.
      * @param fluentBuilder whether fluent builder is allowed as a valid getter/setter
      * @param reference     whether reference parameter (syntax starts with #) is in use
      * @param placeholder   whether to use Camels property placeholder to resolve placeholders on keys and values
      * @return              true if one or more properties was bound
      */
     public static boolean bindProperties(CamelContext camelContext, Object target, Map<String, Object> properties,
-                                         boolean nesting, boolean fluentBuilder, boolean reference, boolean placeholder) {
+                                         boolean nesting, boolean nestingDeep, boolean fluentBuilder, boolean reference, boolean placeholder) {
         org.apache.camel.util.ObjectHelper.notNull(camelContext, "camelContext");
         org.apache.camel.util.ObjectHelper.notNull(target, "target");
         org.apache.camel.util.ObjectHelper.notNull(properties, "properties");
@@ -213,7 +244,7 @@ public final class PropertyBindingSupport {
 
         for (Iterator<Map.Entry<String, Object>> iter = properties.entrySet().iterator(); iter.hasNext();) {
             Map.Entry<String, Object> entry = iter.next();
-            if (bindProperty(camelContext, target, entry.getKey(), entry.getValue(), nesting, fluentBuilder, reference, placeholder)) {
+            if (bindProperty(camelContext, target, entry.getKey(), entry.getValue(), nesting, nestingDeep, fluentBuilder, reference, placeholder)) {
                 iter.remove();
                 rc = true;
             }
@@ -234,7 +265,7 @@ public final class PropertyBindingSupport {
     public static boolean bindProperty(CamelContext camelContext, Object target, String name, Object value) {
         try {
             if (target != null && name != null) {
-                return setProperty(camelContext, target, name, value, true, true, true, true);
+                return setProperty(camelContext, target, name, value, true, true, true, true, true);
             }
         } catch (Exception e) {
             throw new PropertyBindingException(target, name, e);
@@ -244,10 +275,10 @@ public final class PropertyBindingSupport {
     }
 
     private static boolean bindProperty(CamelContext camelContext, Object target, String name, Object value,
-                                boolean nesting, boolean fluentBuilder, boolean reference, boolean placeholder) {
+                                boolean nesting, boolean nestingDeep, boolean fluentBuilder, boolean reference, boolean placeholder) {
         try {
             if (target != null && name != null) {
-                return setProperty(camelContext, target, name, value, nesting, fluentBuilder, reference, placeholder);
+                return setProperty(camelContext, target, name, value, nesting, nestingDeep, fluentBuilder, reference, placeholder);
             }
         } catch (Exception e) {
             throw new PropertyBindingException(target, name, e);
@@ -267,7 +298,7 @@ public final class PropertyBindingSupport {
     public static void bindMandatoryProperty(CamelContext camelContext, Object target, String name, Object value) {
         try {
             if (target != null && name != null) {
-                boolean bound = setProperty(camelContext, target, name, value, true, true, true, true);
+                boolean bound = setProperty(camelContext, target, name, value, true, true, true, true, true);
                 if (!bound) {
                     throw new PropertyBindingException(target, name);
                 }
@@ -278,7 +309,7 @@ public final class PropertyBindingSupport {
     }
 
     private static boolean setProperty(CamelContext context, Object target, String name, Object value,
-                                       boolean nesting, boolean fluentBuilder, boolean reference, boolean placeholder) throws Exception {
+                                       boolean nesting, boolean nestingDeep, boolean fluentBuilder, boolean reference, boolean placeholder) throws Exception {
         String refName = null;
 
         if (placeholder) {
@@ -301,6 +332,10 @@ public final class PropertyBindingSupport {
                     String part = parts[i];
                     Object prop = getOrElseProperty(newTarget, part, null);
                     if (prop == null) {
+                        if (!nestingDeep) {
+                            // okay we cannot go further down
+                            break;
+                        }
                         // okay is there a setter so we can create a new instance and set it automatic
                         Method method = findBestSetterMethod(newClass, part, fluentBuilder);
                         if (method != null) {