Clover coverage report - PicoContainer - 1.0-alpha-2
Coverage timestamp: Thu Jul 10 2003 10:40:43 BST
file stats: LOC: 117   Methods: 3
NCLOC: 60   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
BeanStyleComponentFactory.java 90% 81.2% 100% 84.4%
coverage coverage
 1   
 package picocontainer.extras;
 2   
 
 3   
 import picocontainer.ComponentFactory;
 4   
 import picocontainer.PicoInstantiationException;
 5   
 import picocontainer.PicoIntrospectionException;
 6   
 
 7   
 import java.lang.reflect.Method;
 8   
 import java.lang.reflect.InvocationTargetException;
 9   
 import java.util.List;
 10   
 import java.util.ArrayList;
 11   
 
 12   
 /**
 13   
  * A Component factory that works with Java Bean style components. That is, components that
 14   
  * have an empty constructor and zero or more setXxx methods with one argument to set dependencies.
 15   
  * Note that this ComponentFactory does not use IoC type 3, but rather a "loosely typed" IoC type 1.
 16   
  * (It's loosely typed since no interfaces need to be implemented - as the presence of setXxx
 17   
  * methods in the component implementation classes is enough to have these methods called).
 18   
  * <em>
 19   
  * This class is provided for convenience only, so components adhering to IoC type 1 can be used
 20   
  * without modification. It is however recommended to use {@link picocontainer.defaults.DefaultComponentFactory}
 21   
  * as the basis for component creation, as this leads to a better component design.
 22   
  * </em>
 23   
  *
 24   
  * @author Aslak Helles&oslash;y
 25   
  * @version $Revision: 1.2 $
 26   
  */
 27   
 public class BeanStyleComponentFactory implements ComponentFactory {
 28  3
     public Object createComponent(Class componentType, Class componentImplementation, Class[] dependencies, Object[] instanceDependencies) throws PicoInstantiationException, PicoIntrospectionException {
 29   
         // We'll assume there is an empty constructor
 30  3
         Object result = null;
 31  3
         try {
 32  3
             result = componentImplementation.newInstance();
 33   
         } catch (InstantiationException e) {
 34  0
             throw new RuntimeException("#3 Can we have a concerted effort to try to force these excptions?");
 35   
         } catch (IllegalAccessException e) {
 36  0
             throw new RuntimeException("#4 Can we have a concerted effort to try to force these excptions?");
 37   
         }
 38   
 
 39   
         // Now set the dependencies by calling appropriate methods taking the dependencies as arguments.
 40  3
         Method[] setters = getSetters(componentImplementation);
 41  3
         if (setters.length != instanceDependencies.length) {
 42  0
             throw new IllegalStateException("Unmatching number of dependencies: " + setters.length + " vs " + instanceDependencies.length);
 43   
         }
 44   
 //        List arguments = new ArrayList(Arrays.asList(instanceDependencies));
 45  3
         for (int i = 0; i < setters.length; i++) {
 46  2
             Method setter = setters[i];
 47   
 //            Object argument = extractArgument(arguments,setter);
 48   
             // We can assume order is correct.
 49  2
             Object argument = instanceDependencies[i];
 50  2
             try {
 51  2
                 setter.invoke(result, new Object[]{argument});
 52   
             } catch (IllegalAccessException e) {
 53  0
                 throw new RuntimeException("#5 Can we have a concerted effort to try to force these excptions?");
 54   
             } catch (IllegalArgumentException e) {
 55  0
                 throw new RuntimeException("#6 Can we have a concerted effort to try to force these excptions?");
 56   
             } catch (InvocationTargetException e) {
 57  0
                 throw new RuntimeException("#7 Can we have a concerted effort to try to force these excptions?");
 58   
             }
 59   
         }
 60  3
         return result;
 61   
     }
 62   
 
 63   
     /*
 64   
     Not necessary, since we can assume order is correct.
 65   
 
 66   
     private Object extractArgument(List arguments, Method setter) throws NoArgumentForSetterException {
 67   
         for (Iterator iterator = arguments.iterator(); iterator.hasNext();) {
 68   
             Object argumentCandidate = iterator.next();
 69   
             if( setter.getParameterTypes()[0].isAssignableFrom(argumentCandidate.getClass())) {
 70   
                 // Got it. Remove it so we don't use it again.
 71   
                 iterator.remove();
 72   
                 return argumentCandidate;
 73   
             }
 74   
         }
 75   
         // We didn't find one. That's bad.
 76   
         throw new NoArgumentForSetterException(setter);
 77   
     }
 78   
     */
 79   
 
 80   
     /**
 81   
      * {@inheritDoc}
 82   
      *
 83   
      * The dependencies are resolved by looking at the types of all setXxx methods
 84   
      * taking one parameter.
 85   
      *
 86   
      * @param componentImplementation
 87   
      * @return all classes that are defined in setXxx methods taking one argument.
 88   
      * @throws PicoIntrospectionException
 89   
      */
 90  4
     public Class[] getDependencies(Class componentImplementation) throws PicoIntrospectionException {
 91   
         // TODO use caching.
 92  4
         Method[] setters = getSetters(componentImplementation);
 93  4
         Class[] result = new Class[setters.length];
 94  4
         for (int i = 0; i < result.length; i++) {
 95  2
             result[i] = setters[i].getParameterTypes()[0];
 96   
         }
 97  4
         return result;
 98   
     }
 99   
 
 100  7
     private Method[] getSetters(Class componentImplementation) {
 101   
         // TODO use caching.
 102  7
         List setters = new ArrayList();
 103  7
         Method[] methods = componentImplementation.getMethods();
 104  7
         for (int i = 0; i < methods.length; i++) {
 105  71
             Method method = methods[i];
 106  71
             Class[] parameterTypes = method.getParameterTypes();
 107   
             // We're only interested if there is only one parameter and the method name is bean-style.
 108  71
             boolean hasOneParameter = parameterTypes.length == 1;
 109  71
             boolean isBeanStyle = method.getName().length() >= 4 && method.getName().startsWith("set") && Character.isUpperCase(method.getName().charAt(3));
 110  71
             if (hasOneParameter && isBeanStyle) {
 111  4
                 setters.add(method);
 112   
             }
 113   
         }
 114  7
         return (Method[]) setters.toArray(new Method[setters.size()]);
 115   
     }
 116   
 }
 117