(no commit message)
authorerik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Tue, 10 Jun 2008 21:42:53 +0000 (21:42 +0000)
committererik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Tue, 10 Jun 2008 21:42:53 +0000 (21:42 +0000)
system/general/src/main/java/org/wamblee/system/adapters/SetterConfiguration.java
system/general/src/test/java/org/wamblee/system/adapters/SetterConfigurationTest.java
system/general/src/test/java/org/wamblee/system/adapters/X10.java [new file with mode: 0644]
system/general/src/test/java/org/wamblee/system/adapters/X11.java [new file with mode: 0644]

index 581c5b5913e7513fd5c7d59e37ceeb5c1b1c2429..b2ab5f6d7044745182393717b2809d3a5b5c018b 100644 (file)
@@ -21,12 +21,16 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import org.wamblee.collections.CollectionFilter;
 import org.wamblee.conditions.Condition;
 import org.wamblee.conditions.FixedCondition;
 import org.wamblee.general.Pair;
+import org.wamblee.reflection.ReflectionUtils;
 import org.wamblee.system.core.DefaultProvidedInterface;
 import org.wamblee.system.core.DefaultRequiredInterface;
 import org.wamblee.system.core.ProvidedInterface;
@@ -45,7 +49,7 @@ public class SetterConfiguration {
        private Class _class;
        private boolean _publicOnly;
 
-       private List<Pair<Method, ParameterValues>> _setters;
+       private Map<Method, ParameterValues> _setters;
 
        /**
         * Constructs the setter configuration. By default all setters are added.
@@ -56,19 +60,27 @@ public class SetterConfiguration {
        public SetterConfiguration(Class aClass) {
                _class = aClass;
                _publicOnly = true;
-               _setters = getAllSetters(_class, _publicOnly);
+               initSetters();
+       }
+
+       private void initSetters() {
+               _setters = new HashMap<Method, ParameterValues>();
+               for (Method method: getAllSetters(_class, _publicOnly) ) { 
+                       _setters.put(method, createParameterValues(method));
+               }
        }
 
        /**
         * Called to set whether non-public setters are also used. By default only
-        * public setters are used.
+        * public setters are used. This resets all changes made and selects all
+        * public setters if non-public is false and all setters if it is true.
         * 
         * @param aIsNonPublic
         *            Non public flag.
         */
        public void setNonPublic(boolean aIsNonPublic) {
                _publicOnly = !aIsNonPublic;
-               _setters = getAllSetters(_class, _publicOnly);
+               initSetters();
        }
 
        /**
@@ -90,21 +102,15 @@ public class SetterConfiguration {
         */
        public SetterConfiguration remove(String aName) {
                final String name = createSetterName(aName);
-               List<Pair<Method, ParameterValues>> setters = new ArrayList<Pair<Method, ParameterValues>>();
-               CollectionFilter.filter(_setters, setters,
-                               new Condition<Pair<Method, ParameterValues>>() {
-                                       @Override
-                                       public boolean matches(Pair<Method, ParameterValues> aObject) {
-                                               return !aObject.getFirst().getName().equals(name);
-                                       }
-
-                               });
-               if (_setters.size() == setters.size()) {
-                       throw new IllegalArgumentException(
-                                       "No setter configured by the name of '" + aName + "'");
+               Map<Method, ParameterValues> setters = new HashMap<Method, ParameterValues>();
+               for (Method method : _setters.keySet()) {
+                       if (method.getName().equals(name)) {
+                               _setters.remove(method);
+                               return this;
+                       }
                }
-               _setters = setters;
-               return this;
+               throw new IllegalArgumentException(
+                               "No setter configured by the name of '" + aName + "'");
        }
 
        /**
@@ -128,18 +134,65 @@ public class SetterConfiguration {
        public SetterConfiguration add(String aName) {
                final String name = createSetterName(aName);
                int oldlen = _setters.size();
-               CollectionFilter.filter(getAllSetters(_class, false), _setters,
-                               new Condition<Pair<Method, ParameterValues>>() {
+               List<Method> methods = new ArrayList<Method>();
+               CollectionFilter.filter(getAllSetters(_class, _publicOnly), methods,
+                               new Condition<Method>() {
                                        @Override
-                                       public boolean matches(Pair<Method, ParameterValues> aObject) {
-                                               return aObject.getFirst().getName().equals(name);
+                                       public boolean matches(Method aObject) {
+                                               return aObject.getName().equals(name);
                                        }
 
                                });
-               if (_setters.size() == oldlen) {
+               if (methods.size() == 0 ) {
                        throw new IllegalArgumentException("No setter found for '" + aName
                                        + "' in " + _class.getName());
                }
+               // TODO is it possible to get more than one setter here in case the subclass overrides
+               // the baseclass method? 
+               _setters.put(methods.get(0), createParameterValues(methods.get(0)));
+               return this;
+       }
+
+       /**
+        * Adds a given setter identified by the type it accepts to the list of
+        * setters.N
+        * 
+        * @param aType
+        *            Type to look for. Note that this must be the exact type as
+        *            autoboxing and autounboxing is not used.
+        * @return Reference to the current object to allow call chaining.
+        * @throws IllegalArgumentException
+        *             In case no setter is found or multiple setters are found.
+        */
+       public SetterConfiguration add(final Class aType) {
+               List<Method> result = new ArrayList<Method>();
+               CollectionFilter.filter(getAllSetters(_class, _publicOnly), result,
+                               new Condition<Method>() {
+                                       @Override
+                                       public boolean matches(Method aObject) {
+                                               Class type = aObject.getParameterTypes()[0];
+                                               return type.equals(aType);
+                                       }
+
+                               });
+               if (result.size() == 0) {
+                       throw new IllegalArgumentException("No setter found in class '"
+                                       + _class.getName()
+                                       + "' that has a setter with argument type '"
+                                       + aType.getName() + "'");
+               }
+               if (result.size() > 1) {
+                       String setters = "";
+                       for (Method method : result) {
+                               setters += method.getName() + " ";
+                       }
+                       throw new IllegalArgumentException(
+                                       "Multiple setters found in class '" + _class.getName()
+                                                       + " that accept type '" + aType.getName() + "': "
+                                                       + setters);
+               }
+               Method method = result.get(0);
+               _setters.put(method, createParameterValues(method));
                return this;
        }
 
@@ -148,35 +201,30 @@ public class SetterConfiguration {
         * 
         * @return List of all setters.
         */
-       private static List<Pair<Method, ParameterValues>> getAllSetters(
-                       Class aClass, boolean aPublicOnly) {
-               List<Pair<Method, ParameterValues>> result = new ArrayList<Pair<Method, ParameterValues>>();
+       private static List<Method> getAllSetters(Class aClass,
+                       boolean aPublicOnly) {
+               List<Method> result = new ArrayList<Method>();
                for (Method method : getAllMethods(aClass)) {
                        if (!aPublicOnly || Modifier.isPublic(method.getModifiers())) {
                                if (method.getName().startsWith("set")
                                                && method.getParameterTypes().length == 1) {
                                        method.setAccessible(true);
-                                       String name = getSetterName(method);
-                                       result
-                                                       .add(new Pair<Method, ParameterValues>(method,
-                                                                       new ParameterValues(new String[] { name },
-                                                                                       new Class[] { method
-                                                                                                       .getParameterTypes()[0] })));
+                                       result.add(method);
                                }
                        }
                }
                return result;
        }
 
+       private static ParameterValues createParameterValues(Method method) {
+               return new ParameterValues(
+                               new String[] { getSetterName(method) }, new Class[] { method
+                                               .getParameterTypes()[0] });
+       }
+
        private static final List<Method> getAllMethods(Class aClass) {
-       List<Method> result = new ArrayList<Method>();
-       result.addAll(Arrays.asList(aClass.getDeclaredMethods()));
-       Class superClass = aClass.getSuperclass();
-       if ( superClass != null ) { 
-               result.addAll(getAllMethods(superClass));
-       }
-       return result; 
-    }
+               return ReflectionUtils.getAllMethods(aClass);
+       }
 
        /**
         * Gets the required interfaces based on the configured setteres.
@@ -185,8 +233,8 @@ public class SetterConfiguration {
         */
        public List<RequiredInterface> getRequiredInterfaces() {
                List<RequiredInterface> result = new ArrayList<RequiredInterface>();
-               for (Pair<Method, ParameterValues> method : _setters) {
-                       result.addAll(method.getSecond().getRequiredInterfaces());
+               for (Method method : _setters.keySet()) {
+                       result.addAll(_setters.get(method).getRequiredInterfaces());
                }
                return result;
        }
@@ -204,9 +252,8 @@ public class SetterConfiguration {
                        throw new IllegalArgumentException("Object '" + aObject
                                        + "' is not an instance of " + _class.getName());
                }
-               for (Pair<Method, ParameterValues> setter : _setters) {
-                       Method method = setter.getFirst();
-                       ParameterValues values = setter.getSecond();
+               for (Method method : _setters.keySet()) {
+                       ParameterValues values = _setters.get(method);
 
                        try {
                                method.invoke(aObject, values.values(aScope));
@@ -231,9 +278,9 @@ public class SetterConfiguration {
         */
        public ParameterValues values(String aMethod) {
                String name = createSetterName(aMethod);
-               for (Pair<Method, ParameterValues> method : _setters) {
-                       if (method.getFirst().getName().equals(name)) {
-                               return method.getSecond();
+               for (Method method : _setters.keySet()) {
+                       if (method.getName().equals(name)) {
+                               return _setters.get(method);
                        }
                }
                throw new IllegalArgumentException("No setter method '" + name
@@ -254,4 +301,7 @@ public class SetterConfiguration {
                return result.substring(0, 1).toLowerCase() + result.substring(1);
        }
 
+       public List<Method> getSetters() { 
+               return new ArrayList<Method>(_setters.keySet());
+       }
 }
index 2b7bd9187477d85981057caa10d8580edce682e9..730dfe6d84329d2d284999a72ccdaf386385af8d 100644 (file)
  */
 package org.wamblee.system.adapters;
 
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
+import javax.sql.DataSource;
+
 import org.wamblee.system.core.DefaultProvidedInterface;
 import org.wamblee.system.core.ProvidedInterface;
 import org.wamblee.system.core.RequiredInterface;
@@ -201,7 +204,7 @@ public class SetterConfigurationTest extends AdapterTestCase {
                assertNull(obj.getPort());
        }
 
-       public void testAdd() {
+       public void testAddByName() {
                SetterConfiguration config = new SetterConfiguration(X6.class);
                config.clear().add("host");
                List<RequiredInterface> required = config.getRequiredInterfaces();
@@ -222,6 +225,44 @@ public class SetterConfigurationTest extends AdapterTestCase {
                assertEquals("hello", obj.getHost());
                assertNull(obj.getPort());
        }
+       
+       public void testAddByType() { 
+               SetterConfiguration config = new SetterConfiguration(X6.class);
+               config.clear().add(String.class);
+               List<RequiredInterface> required = config.getRequiredInterfaces();
+               Collections.sort(required, new RequiredInterfaceComparator());
+               assertEquals(1, required.size());
+               assertEquals("host", required.get(0).getName());
+
+               ProvidedInterface provided0 = new DefaultProvidedInterface("janse",
+                               String.class);
+               required.get(0).setProvider(provided0);
+               provided0.publish("hello", _scope);
+
+               X6 obj = new X6();
+               assertNull(obj.getHost());
+               assertNull(obj.getPort());
+
+               config.inject(_scope, obj);
+               assertEquals("hello", obj.getHost());
+               assertNull(obj.getPort());
+       }
+       
+       public void testAddPrivate() { 
+               X5 obj = new X5();
+               final SetterConfiguration config = new SetterConfiguration(X5.class);
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { 
+                       @Override
+                       public void run() throws Exception {
+                               config.add("xyz");      
+                       }
+               }, IllegalArgumentException.class);
+               
+               config.setNonPublic(true);
+               config.clear();
+               config.add("xyz");
+               assertEquals(1, config.getRequiredInterfaces().size());
+       }
 
        public void testAddNonExisting() {
                final SetterConfiguration config = new SetterConfiguration(X6.class);
@@ -233,6 +274,23 @@ public class SetterConfigurationTest extends AdapterTestCase {
                                config.add("bladibla");
                        }
                }, IllegalArgumentException.class);
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               config.add(DataSource.class);
+                       }
+               }, IllegalArgumentException.class);
+       }
+       
+       public void testAddByTypeNonUnique() { 
+               final SetterConfiguration config = new SetterConfiguration(X11.class);
+               config.clear();
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               config.add(String.class);
+                       }
+               }, IllegalArgumentException.class);
        }
 
        public void testRemove() {
@@ -267,4 +325,15 @@ public class SetterConfigurationTest extends AdapterTestCase {
                        }
                }, IllegalArgumentException.class);
        }
+       
+       public void testOverridingSetters() { 
+               SetterConfiguration config = new SetterConfiguration(X10.class);
+               assertEquals(2, config.getRequiredInterfaces().size());
+               List<Method> methods = config.getSetters(); 
+               assertEquals(2, methods.size());
+               for (Method method: methods) { 
+                       assertEquals(X10.class, method.getDeclaringClass());
+               }
+               
+       }
 }
diff --git a/system/general/src/test/java/org/wamblee/system/adapters/X10.java b/system/general/src/test/java/org/wamblee/system/adapters/X10.java
new file mode 100644 (file)
index 0000000..fc8b90a
--- /dev/null
@@ -0,0 +1,26 @@
+package org.wamblee.system.adapters;
+
+public class X10 extends X6 {
+
+       
+       @Override
+       public void setHost(String aHost) {
+               super.setHost(aHost);
+       }
+       
+       @Override
+       public String getHost() {
+               return super.getHost();
+       }
+       
+       @Override
+       public Integer getPort() {
+               return super.getPort();
+       }
+       
+       @Override
+       public void setPort(Integer aPort) {
+               super.setPort(aPort);
+       }
+       
+}
diff --git a/system/general/src/test/java/org/wamblee/system/adapters/X11.java b/system/general/src/test/java/org/wamblee/system/adapters/X11.java
new file mode 100644 (file)
index 0000000..4ddc11e
--- /dev/null
@@ -0,0 +1,14 @@
+package org.wamblee.system.adapters;
+
+public class X11 {
+       
+       
+       public void setX(String aValue) { 
+               
+       }
+       
+       public void setY(String aValue) { 
+               
+       }
+
+}