Re: [picocontainer-dev] ConfigParameterTestCase / ConfigParameter

Paul Hammant <[email protected]>
Newsgroups gmane.comp.java.picocontainer.devel
Message-ID <[email protected]>
Here it is again with reflection using converters, as per Jörgs  
suggestions -

public class BasicComponentParameter implements Parameter,  
Serializable {

     private static interface Converter {
         Object convert(String paramValue);
     }
     private static class ValueOfConverter implements Converter {
         private Method m;
         private ValueOfConverter(Class clazz) {
             try {
                 m = clazz.getMethod("valueOf", String.class);
             } catch (NoSuchMethodException e) {
             }
         }

         public Object convert(String paramValue) {
             try {
                 return m.invoke(null, paramValue);
             } catch (IllegalAccessException e) {
             } catch (InvocationTargetException e) {
             }
             return null;

         }
     }
     private static class NewInstanceConverter implements Converter {
         private Constructor c;

         private NewInstanceConverter(Class clazz) {
             try {
                 c = clazz.getConstructor(String.class);
             } catch (NoSuchMethodException e) {
             }
         }

         public Object convert(String paramValue) {
             try {
                 return c.newInstance(paramValue);
             } catch (IllegalAccessException e) {
             } catch (InvocationTargetException e) {
             } catch (InstantiationException e) {
             }
             return null;
         }
     }

     private static final Map<Class, Converter> stringConverters =  
new HashMap<Class, Converter>();
     static {
         stringConverters.put(Integer.class, new ValueOfConverter 
(Integer.class));
         stringConverters.put(Double.class, new ValueOfConverter 
(Double.class));
         stringConverters.put(Boolean.class, new ValueOfConverter 
(Boolean.class));
         stringConverters.put(Long.class, new ValueOfConverter 
(Long.class));
         stringConverters.put(Float.class, new ValueOfConverter 
(Float.class));
         stringConverters.put(Character.class, new ValueOfConverter 
(Character.class));
         stringConverters.put(Byte.class, new ValueOfConverter 
(Byte.class));
         stringConverters.put(Byte.class, new ValueOfConverter 
(Short.class));
         stringConverters.put(File.class, new NewInstanceConverter 
(File.class));

     }


Its all in core, with no deps on gems or XStream for this functionality.
TODO -

1) look at ConfigParameter again and potentially consolidate some of  
the functionality
2) review ArgumentativePicoContaine, SystemPropertiesPicoContainer  
and PropertiesPicoContainer  for overlap/redunctancy

- Paul

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email
improved.txt (text/plain, 15.1 KB)
Index: src/test/org/picocontainer/containers/ArgumentativePicoContainerTestCase.java
===================================================================
--- src/test/org/picocontainer/containers/ArgumentativePicoContainerTestCase.java	(revision 4004)
+++ src/test/org/picocontainer/containers/ArgumentativePicoContainerTestCase.java	(working copy)
@@ -28,9 +28,9 @@
             "foo=bar", "foo2=12", "foo3=true", "foo4="
         });
         assertEquals("bar",apc.getComponent("foo"));
-        assertEquals(12,apc.getComponent("foo2"));
-        assertEquals(true,apc.getComponent("foo3"));
-        assertEquals(true,apc.getComponent("foo4"));
+        assertEquals("12",apc.getComponent("foo2"));
+        assertEquals("true",apc.getComponent("foo3"));
+        assertEquals("true",apc.getComponent("foo4"));
     }
 
     public void testAsParentContainer() {
@@ -38,7 +38,7 @@
             "a=aaa", "b=bbb", "d=22"});
         assertEquals("aaa",apc.getComponent("a"));
         assertEquals("bbb",apc.getComponent("b"));
-        assertEquals(22,apc.getComponent("d"));
+        assertEquals("22",apc.getComponent("d"));
 
         DefaultPicoContainer dpc = new DefaultPicoContainer(apc);
         dpc.addComponent(NeedsString.class);
@@ -57,41 +57,41 @@
             "foo:bar", "foo2:12", "foo3:true"
         });
         assertEquals("bar",apc.getComponent("foo"));
-        assertEquals(12,apc.getComponent("foo2"));
-        assertEquals(true,apc.getComponent("foo3"));
+        assertEquals("12",apc.getComponent("foo2"));
+        assertEquals("true",apc.getComponent("foo3"));
     }
 
     public void testParsingWithWrongSeparator() {
         ArgumentativePicoContainer apc = new ArgumentativePicoContainer(":", new String[] {
             "foo=bar", "foo2=12", "foo3=true"
         });
-        assertEquals(true,apc.getComponent("foo=bar"));
-        assertEquals(true,apc.getComponent("foo2=12"));
-        assertEquals(true,apc.getComponent("foo3=true"));
+        assertEquals("true",apc.getComponent("foo=bar"));
+        assertEquals("true",apc.getComponent("foo2=12"));
+        assertEquals("true",apc.getComponent("foo3=true"));
     }
 
     public void testParsingOfPropertiesFile() throws IOException {
         ArgumentativePicoContainer apc = new ArgumentativePicoContainer(":",
                                new StringReader("foo:bar\nfoo2:12\nfoo3:true\n"));
         assertEquals("bar",apc.getComponent("foo"));
-        assertEquals(12,apc.getComponent("foo2"));
-        assertEquals(true,apc.getComponent("foo3"));
+        assertEquals("12",apc.getComponent("foo2"));
+        assertEquals("true",apc.getComponent("foo3"));
     }
 
     public void testParsingOfPropertiesFileAndArgs() throws IOException {
         ArgumentativePicoContainer apc = new ArgumentativePicoContainer(":",
                                new StringReader("foo:bar\nfoo2:12\n"), new String[] {"foo3:true"});
         assertEquals("bar",apc.getComponent("foo"));
-        assertEquals(12,apc.getComponent("foo2"));
-        assertEquals(true,apc.getComponent("foo3"));
+        assertEquals("12",apc.getComponent("foo2"));
+        assertEquals("true",apc.getComponent("foo3"));
     }
 
     public void testParsingOfPropertiesFileAndArgsWithClash() throws IOException {
         ArgumentativePicoContainer apc = new ArgumentativePicoContainer(":",
                                new StringReader("foo:bar\nfoo2:99\n"), new String[] {"foo2:12","foo3:true"});
         assertEquals("bar",apc.getComponent("foo"));
-        assertEquals(12,apc.getComponent("foo2"));
-        assertEquals(true,apc.getComponent("foo3"));
+        assertEquals("12",apc.getComponent("foo2"));
+        assertEquals("true",apc.getComponent("foo3"));
     }
 
     public void testbyTypeFailsEvenIfOneOfSameType() {
Index: src/java/org/picocontainer/parameters/BasicComponentParameter.java
===================================================================
--- src/java/org/picocontainer/parameters/BasicComponentParameter.java	(revision 4004)
+++ src/java/org/picocontainer/parameters/BasicComponentParameter.java	(working copy)
@@ -16,10 +16,15 @@
 import org.picocontainer.PicoVisitor;
 import org.picocontainer.injectors.AbstractInjector;
 
+import java.io.File;
 import java.io.Serializable;
-import java.lang.reflect.Field;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -35,15 +40,72 @@
  * @author J&ouml;rg Schaible
  * @author Thomas Heller
  */
-public class BasicComponentParameter
-    implements Parameter, Serializable
-{
+public class BasicComponentParameter implements Parameter, Serializable {
 
+    private static interface Converter {
+        Object convert(String paramValue);
+    }
+    private static class ValueOfConverter implements Converter {
+        private Method m;
+        private ValueOfConverter(Class clazz) {
+            try {
+                m = clazz.getMethod("valueOf", String.class);
+            } catch (NoSuchMethodException e) {
+            }
+        }
+
+        public Object convert(String paramValue) {
+            try {
+                return m.invoke(null, paramValue);
+            } catch (IllegalAccessException e) {
+            } catch (InvocationTargetException e) {
+            }
+            return null;
+
+        }
+    }
+    private static class NewInstanceConverter implements Converter {
+        private Constructor c;
+
+        private NewInstanceConverter(Class clazz) {
+            try {
+                c = clazz.getConstructor(String.class);
+            } catch (NoSuchMethodException e) {
+            }
+        }
+
+        public Object convert(String paramValue) {
+            try {
+                return c.newInstance(paramValue);
+            } catch (IllegalAccessException e) {
+            } catch (InvocationTargetException e) {
+            } catch (InstantiationException e) {
+            }
+            return null;
+        }
+    }
+
     /** <code>BASIC_DEFAULT</code> is an instance of BasicComponentParameter using the default constructor. */
     public static final BasicComponentParameter BASIC_DEFAULT = new BasicComponentParameter();
 
     private Object componentKey;
 
+
+    private static final Map<Class, Converter> stringConverters = new HashMap<Class, Converter>();
+    static {
+        stringConverters.put(Integer.class, new ValueOfConverter(Integer.class));
+        stringConverters.put(Double.class, new ValueOfConverter(Double.class));
+        stringConverters.put(Boolean.class, new ValueOfConverter(Boolean.class));
+        stringConverters.put(Long.class, new ValueOfConverter(Long.class));
+        stringConverters.put(Float.class, new ValueOfConverter(Float.class));
+        stringConverters.put(Character.class, new ValueOfConverter(Character.class));
+        stringConverters.put(Byte.class, new ValueOfConverter(Byte.class));
+        stringConverters.put(Byte.class, new ValueOfConverter(Short.class));
+        stringConverters.put(File.class, new NewInstanceConverter(File.class));
+
+    }
+
+
     /**
      * Expect a parameter matching a component of a specific key.
      *
@@ -80,7 +142,12 @@
         final ComponentAdapter componentAdapter =
             resolveAdapter(container, adapter, (Class<?>)expectedType, expectedParameterName, useNames);
         if (componentAdapter != null) {
-            return (T) container.getComponent(componentAdapter.getComponentKey());
+            Object o = container.getComponent(componentAdapter.getComponentKey());
+            if (o instanceof String && expectedType != String.class) {
+                Converter converter = stringConverters.get(expectedType);
+                return (T) converter.convert((String) o);
+            }
+            return (T) o;
         }
         return null;
     }
@@ -112,32 +179,37 @@
                                                    ComponentAdapter adapter,
                                                    Class<T> expectedType,
                                                    ParameterName expectedParameterName, boolean useNames) {
+        Class type = expectedType;
+        if (type.isPrimitive()) {
+            String expectedTypeName = expectedType.getName();
+            if (expectedTypeName == "int") {
+                type = Integer.class;
+            } else if (expectedTypeName == "long") {
+                type = Long.class;
+            } else if (expectedTypeName == "float") {
+                type = Float.class;
+            } else if (expectedTypeName == "double") {
+                type = Double.class;
+            } else if (expectedTypeName == "boolean") {
+                type = Boolean.class;
+            } else if (expectedTypeName == "char") {
+                type = Character.class;
+            } else if (expectedTypeName == "short") {
+                type = Short.class;
+            } else if (expectedTypeName == "byte") {
+                type = Byte.class;
+            }
+        }
 
-        final ComponentAdapter<T> result = getTargetAdapter(container, expectedType, expectedParameterName, adapter, useNames);
+        final ComponentAdapter<T> result = getTargetAdapter(container, type, expectedParameterName, adapter, useNames);
         if (result == null) {
             return null;
         }
 
-        if (!expectedType.isAssignableFrom(result.getComponentImplementation())) {
-            // check for primitive value
-            if (expectedType.isPrimitive()) {
-                try {
-                    final Field field = result.getComponentImplementation().getField("TYPE");
-                    final Class type = (Class)field.get(result.getComponentInstance(null));
-                    if (expectedType.isAssignableFrom(type)) {
-                        return result;
-                    }
-                } catch (NoSuchFieldException e) {
-                    //ignore
-                } catch (IllegalArgumentException e) {
-                    //ignore
-                } catch (IllegalAccessException e) {
-                    //ignore
-                } catch (ClassCastException e) {
-                    //ignore
-                }
+        if (!type.isAssignableFrom(result.getComponentImplementation())) {
+            if (!(result.getComponentImplementation() == String.class && stringConverters.containsKey(type))) {
+                return null;
             }
-            return null;
         }
         return result;
     }
@@ -166,7 +238,7 @@
             if (useNames) {
                 ComponentAdapter found = container.getComponentAdapter(expectedParameterName.getName());
                 if ((found != null)
-                    && expectedType.isAssignableFrom(found.getComponentImplementation())
+                    && areCompatible(expectedType, found)
                     && found != excludeAdapter) {
                     return (ComponentAdapter<T>) found;                    
                 }
@@ -196,4 +268,10 @@
             }
         }
     }
+
+    private <T> boolean areCompatible(Class<T> expectedType, ComponentAdapter found) {
+        Class foundImpl = found.getComponentImplementation();
+        return expectedType.isAssignableFrom(foundImpl) ||
+               (foundImpl == String.class && stringConverters.containsKey(expectedType))  ;
+    }
 }
Index: src/java/org/picocontainer/injectors/SingleMemberInjector.java
===================================================================
--- src/java/org/picocontainer/injectors/SingleMemberInjector.java	(revision 4004)
+++ src/java/org/picocontainer/injectors/SingleMemberInjector.java	(working copy)
@@ -46,10 +46,23 @@
      */
     protected Class box(Class parameterType) {
         if (parameterType.isPrimitive()) {
-            if (parameterType == Integer.TYPE) {
+            String parameterTypeName = parameterType.getName();
+            if (parameterTypeName == "int") {
                 return Integer.class;
-            } else if (parameterType == Boolean.TYPE) {
+            } else if (parameterTypeName == "boolean") {
                 return Boolean.class;
+            } else if (parameterTypeName == "long") {
+                return Long.class;
+            } else if (parameterTypeName == "float") {
+                return Float.class;
+            } else if (parameterTypeName == "double") {
+                return Double.class;
+            } else if (parameterTypeName == "char") {
+                return Character.class;
+            } else if (parameterTypeName == "byte") {
+                return Byte.class;
+            } else if (parameterTypeName == "short") {
+                return Short.class;
             }
         }
         return parameterType;
Index: src/java/org/picocontainer/injectors/ConstructorInjector.java
===================================================================
--- src/java/org/picocontainer/injectors/ConstructorInjector.java	(revision 4004)
+++ src/java/org/picocontainer/injectors/ConstructorInjector.java	(working copy)
@@ -78,9 +78,11 @@
 
             // remember: all constructors with less arguments than the given parameters are filtered out already
             for (int j = 0; j < currentParameters.length; j++) {
-                // check wether this constructor is statisfiable
-                if (currentParameters[j].isResolvable(container, this, box(parameterTypes[j]),
-                         new SingleMemberInjectorParameterName(sortedMatchingConstructor,j), useNames())) {
+                // check whether this constructor is statisfiable
+                Class boxed = box(parameterTypes[j]);
+                boolean un = useNames();
+                if (currentParameters[j].isResolvable(container, this, boxed,
+                    new SingleMemberInjectorParameterName(sortedMatchingConstructor, j), un)) {
                     continue;
                 }
                 unsatisfiableDependencyTypes.add(Arrays.asList(parameterTypes));
Index: src/java/org/picocontainer/containers/ArgumentativePicoContainer.java
===================================================================
--- src/java/org/picocontainer/containers/ArgumentativePicoContainer.java	(revision 4004)
+++ src/java/org/picocontainer/containers/ArgumentativePicoContainer.java	(working copy)
@@ -88,25 +88,12 @@
         return new EmptyPicoContainer();
     }
 
-    private Object getValue(String s) {
-        if (s.equals("true")) {
-            return true;
-        } else if (s.equals("false")) {
-            return false;
-        }
-        try {
-            return Integer.parseInt(s);
-        } catch (NumberFormatException e) {
-        }
-        return s;
-    }
-
     private void processArgument(String argument, String separator) {
         String[] kvs = argument.split(separator);
         if (kvs.length == 2) {
-            addConfig(kvs[0], getValue(kvs[1]));
+            addConfig(kvs[0], kvs[1]);
         } else if (kvs.length == 1) {
-            addConfig(kvs[0], true);
+            addConfig(kvs[0], "true");
         } else if (kvs.length > 2) {
             throw new PicoCompositionException(
                 "Argument name'"+separator+"'value pair '" + argument + "' has too many '"+separator+"' characters");
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.