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 2008/08/21 14:51:23 UTC

svn commit: r687732 - in /activemq/camel/trunk/camel-core/src: main/java/org/apache/camel/util/IntrospectionSupport.java test/java/org/apache/camel/util/IntrospectionSupportTest.java

Author: davsclaus
Date: Thu Aug 21 05:51:21 2008
New Revision: 687732

URL: http://svn.apache.org/viewvc?rev=687732&view=rev
Log:
CAMEL-840: IntrospectionSupport to support overloaded setter methods for setting properties.

Added:
    activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java   (with props)
Modified:
    activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java

Modified: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java?rev=687732&r1=687731&r2=687732&view=diff
==============================================================================
--- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java (original)
+++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java Thu Aug 21 05:51:21 2008
@@ -28,6 +28,7 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
 
@@ -180,21 +181,42 @@
     public static boolean setProperty(TypeConverter typeConverter, Object target, String name, Object value) throws Exception {
         try {
             Class clazz = target.getClass();
-            Method setter = findSetterMethod(typeConverter, clazz, name, value);
-            if (setter == null) {
+            // find candidates of setter methods as there can be overloaded setters
+            Set<Method> setters = findSetterMethods(typeConverter, clazz, name, value);
+            if (setters.isEmpty()) {
                 return false;
             }
 
-            // If the type is null or it matches the needed type, just use the
-            // value directly
-            if (value == null || value.getClass() == setter.getParameterTypes()[0]) {
-                setter.invoke(target, value);
+            // loop and execute the best setter method
+            Exception typeConvertionFailed = null;
+            for (Method setter : setters) {
+                // If the type is null or it matches the needed type, just use the value directly
+                if (value == null || value.getClass() == setter.getParameterTypes()[0]) {
+                    setter.invoke(target, value);
+                    return true;
+                } else {
+                    // We need to convert it
+                    try {
+                        Object convertedValue = convert(typeConverter, setter.getParameterTypes()[0], value);
+                        setter.invoke(target, convertedValue);
+                        return true;
+                    } catch (IllegalArgumentException e) {
+                        typeConvertionFailed = e;
+                        // ignore as there could be another setter method where we could type convert with success
+                        LOG.trace("Setter " + setter + " with parameter type " + setter.getParameterTypes()[0]
+                                + " could not be used for type conertions of " + value);
+                    }
+                }
+            }
+            // we did not find a setter method to use, and if we did try to use a type converter then throw
+            // this kind of exception as the caused by will hint this error
+            if (typeConvertionFailed != null) {
+                throw new IllegalArgumentException("Could not find a suitable setter for property: " + name
+                        + " as there isn't a setter method with same type: " + value.getClass().getCanonicalName()
+                        + " nor type convertion possbile: " + typeConvertionFailed.getMessage());
             } else {
-                // We need to convert it
-                Object convertedValue = convert(typeConverter, setter.getParameterTypes()[0], value);
-                setter.invoke(target, convertedValue);
+                return false;
             }
-            return true;
         } catch (InvocationTargetException e) {
             Throwable throwable = e.getTargetException();
             if (throwable instanceof Exception) {
@@ -242,7 +264,9 @@
         return null;
     }
 
-    private static Method findSetterMethod(TypeConverter typeConverter, Class clazz, String name, Object value) {
+    private static Set<Method> findSetterMethods(TypeConverter typeConverter, Class clazz, String name, Object value) {
+        Set<Method> candidates = new LinkedHashSet<Method>();
+
         // Build the method name.
         name = "set" + ObjectHelper.capitalize(name);
         while (clazz != Object.class) {
@@ -252,13 +276,38 @@
                 if (method.getName().equals(name) && params.length == 1) {
                     Class paramType = params[0];
                     if (typeConverter != null || isSettableType(paramType) || paramType.isInstance(value)) {
-                        return method;
+                        candidates.add(method);
                     }
                 }
             }
             clazz = clazz.getSuperclass();
         }
-        return null;
+
+        if (candidates.isEmpty()) {
+            return candidates;
+        } else if (candidates.size() == 1 ){
+            // only one
+            return candidates;
+        } else {
+            // find the best match if possible
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("Found " + candidates.size() + " suitable setter methods for setting " + name);
+            }
+            // perfer to use the one with the same instance if any exists
+            for (Method method : candidates) {
+                if (method.getParameterTypes()[0].isInstance(value)) {
+                    if (LOG.isTraceEnabled()) {
+                        LOG.trace("Method " + method + " is the best candidate as it has parameter with same instance type");
+                    }
+                    // retain only this method in the answer
+                    candidates.clear();
+                    candidates.add(method);
+                    return candidates;
+                }
+            }
+            // fallback to return what we have found as candidates so far
+            return candidates;
+        }
     }
 
     private static boolean isSettableType(Class clazz) {

Added: activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java?rev=687732&view=auto
==============================================================================
--- activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java (added)
+++ activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java Thu Aug 21 05:51:21 2008
@@ -0,0 +1,59 @@
+/**
+ * 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.util;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.util.jndi.ExampleBean;
+
+/**
+ * Unit test for IntrospectionSupport 
+ */
+public class IntrospectionSupportTest extends ContextTestSupport {
+
+    public void testOverloadSetterChooseStringSetter() throws Exception {
+        MyOverloadedBean overloadedBean = new MyOverloadedBean();
+        IntrospectionSupport.setProperty(context.getTypeConverter(), overloadedBean, "bean", "James");
+        assertEquals("James", overloadedBean.getName());
+    }
+
+    public void testOverloadSetterChooseBeanSetter() throws Exception {
+        MyOverloadedBean overloadedBean = new MyOverloadedBean();
+        ExampleBean bean = new ExampleBean();
+        bean.setName("Claus");
+        IntrospectionSupport.setProperty(context.getTypeConverter(), overloadedBean, "bean", bean);
+        assertEquals("Claus", overloadedBean.getName());
+    }
+
+    public class MyOverloadedBean {
+        private ExampleBean bean;
+
+        public void setBean(ExampleBean bean) {
+            this.bean = bean;
+        }
+
+        public void setBean(String name) {
+            bean = new ExampleBean();
+            bean.setName(name);
+        }
+
+        public String getName() {
+            return bean.getName();
+        }
+    }
+
+}
+

Propchange: activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date