Clover coverage report - PicoContainer - 1.0-RC-1
Coverage timestamp: Tue May 18 2004 16:19:33 EDT
file stats: LOC: 169   Methods: 4
NCLOC: 122   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
SetterInjectionComponentAdapter.java 82.4% 85.3% 100% 84.9%
coverage coverage
 1   
 /*****************************************************************************
 2   
  * Copyright (C) PicoContainer Organization. All rights reserved.            *
 3   
  * ------------------------------------------------------------------------- *
 4   
  * The software in this package is published under the terms of the BSD      *
 5   
  * style license a copy of which has been included with this distribution in *
 6   
  * the LICENSE.txt file.                                                     *
 7   
  *                                                                           *
 8   
  * Original code by                                                          *
 9   
  *****************************************************************************/
 10   
 package org.picocontainer.defaults;
 11   
 
 12   
 import org.picocontainer.ComponentAdapter;
 13   
 import org.picocontainer.PicoInitializationException;
 14   
 import org.picocontainer.PicoIntrospectionException;
 15   
 import org.picocontainer.Parameter;
 16   
 
 17   
 import java.lang.reflect.Constructor;
 18   
 import java.lang.reflect.InvocationTargetException;
 19   
 import java.lang.reflect.Method;
 20   
 import java.util.ArrayList;
 21   
 import java.util.Collections;
 22   
 import java.util.HashSet;
 23   
 import java.util.List;
 24   
 import java.util.Set;
 25   
 
 26   
 /**
 27   
  * Instantiates components using empty constructors and
 28   
  * <a href="http://docs.codehaus.org/display/PICO/Setter+Injection">Setter Injection</a>.
 29   
  * For easy setting of primitive properties, also see {@link BeanPropertyComponentAdapter}.
 30   
  * <p/>
 31   
  * <em>
 32   
  * Note that this class doesn't cache instances. If you want caching,
 33   
  * use a {@link CachingComponentAdapter} around this one.
 34   
  * </em>
 35   
  *
 36   
  * @author Aslak Helles&oslash;y
 37   
  * @author J&ouml;rg Schaible
 38   
  * @version $Revision: 1.3 $
 39   
  */
 40   
 public class SetterInjectionComponentAdapter extends InstantiatingComponentAdapter {
 41   
     private transient boolean instantiating;
 42   
     private transient List setters;
 43   
     private transient List setterNames;
 44   
     private transient Class[] setterTypes;
 45   
 
 46   
     /**
 47   
      * Explicitly specifies parameters, if null uses default parameters.
 48   
      * {@inheritDoc}
 49   
      */
 50  22
     public SetterInjectionComponentAdapter(final Object componentKey,
 51   
                                        final Class componentImplementation,
 52   
                                        Parameter[] parameters) throws AssignabilityRegistrationException, NotConcreteRegistrationException {
 53  22
         super(componentKey, componentImplementation, parameters);
 54   
     }
 55   
 
 56   
     /**
 57   
      * @see org.picocontainer.defaults.InstantiatingComponentAdapter#getGreediestSatisifableConstructor(java.util.List)
 58   
      */
 59  19
     protected Constructor getGreediestSatisifableConstructor(List adapterInstantiationOrderTrackingList) throws PicoIntrospectionException, UnsatisfiableDependenciesException, AmbiguousComponentResolutionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
 60  19
         final Constructor constructor;
 61  19
         try {
 62  19
             constructor = getComponentImplementation().getConstructor(null);
 63   
         } catch (NoSuchMethodException e) {
 64  1
             throw new PicoInvocationTargetInitializationException(e);
 65   
         } catch (SecurityException e) {
 66  0
             throw new PicoInvocationTargetInitializationException(e);
 67   
         }
 68   
         
 69  18
         if(setters == null) {
 70  17
             initializeSetterAndTypeLists();
 71   
         }
 72   
 
 73  18
         final List matchingTypeList = new ArrayList(Collections.nCopies(setters.size(), null));
 74  18
         final Set nonMatchingParameterPositions = new HashSet();
 75  18
         final Parameter[] currentParameters = parameters != null ? parameters : createDefaultParameters(setterTypes);
 76  18
         for (int i = 0; i < currentParameters.length; i++) {
 77  34
             final Parameter parameter = currentParameters[i];
 78  34
             boolean failedDependency = true;
 79  34
             for(int j = 0; j < setterTypes.length; j++) {
 80  66
                 if (matchingTypeList.get(j) == null) {
 81  36
                     final ComponentAdapter adapter = parameter.resolveAdapter(getContainer(), setterTypes[j]);
 82  36
                     if (adapter != null && !adapter.equals(this) && !getComponentKey().equals(adapter.getComponentKey())) {
 83  32
                         matchingTypeList.set(j, adapter);
 84  32
                         failedDependency = false;
 85  32
                         break;
 86   
                     }
 87   
                 }
 88   
             }
 89  34
             if(failedDependency) {
 90  2
                 nonMatchingParameterPositions.add(new Integer(i));
 91   
             }
 92   
         }
 93   
         
 94  18
         final Set unsatisfiableDependencyTypes = new HashSet();
 95  18
         for (int i = 0; i < matchingTypeList.size(); i++) {
 96  34
             if (matchingTypeList.get(i) == null) {
 97  2
                 unsatisfiableDependencyTypes.add(setterTypes[i]);
 98   
             }
 99   
         }
 100  18
         if (unsatisfiableDependencyTypes.size() > 0) {
 101  1
             throw new UnsatisfiableDependenciesException(this, unsatisfiableDependencyTypes);
 102   
         }
 103   
 
 104  17
         if (nonMatchingParameterPositions.size() > 0) {
 105  0
             throw new PicoInitializationException("Following parameters do not match any of the setters for "
 106   
                     + getComponentImplementation() +  ": " + nonMatchingParameterPositions.toString());
 107   
         }
 108  17
         adapterInstantiationOrderTrackingList.addAll(matchingTypeList);
 109  17
         return constructor;
 110   
     }
 111   
 
 112   
     /**
 113   
      * @see org.picocontainer.defaults.InstantiatingComponentAdapter#instantiateComponent(java.util.List)
 114   
      */
 115  19
     protected Object instantiateComponent(List adapterInstantiationOrderTrackingList) throws PicoInitializationException, PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
 116  19
         try {
 117  19
             final Constructor constructor = getGreediestSatisifableConstructor(adapterInstantiationOrderTrackingList);
 118  17
             if (instantiating) {
 119  0
                 throw new CyclicDependencyException(setterTypes);
 120   
             }
 121  17
             instantiating = true;
 122  17
             final Object componentInstance = constructor.newInstance(null);
 123  17
             for (int i = 0; i < setters.size(); i++) {
 124  31
                 final Method setter = (Method)setters.get(i);
 125  31
                 final ComponentAdapter adapter = (ComponentAdapter)adapterInstantiationOrderTrackingList.get(i);
 126  31
                 setter.invoke(componentInstance, new Object[]{ adapter.getComponentInstance() });
 127   
             }
 128   
 
 129  17
             return componentInstance;
 130   
         } catch (InvocationTargetException e) {
 131  0
             if (e.getTargetException() instanceof RuntimeException) {
 132  0
                 throw (RuntimeException) e.getTargetException();
 133  0
             } else if (e.getTargetException() instanceof Error) {
 134  0
                 throw (Error) e.getTargetException();
 135   
             }
 136  0
             throw new PicoInvocationTargetInitializationException(e.getTargetException());
 137   
         } catch (InstantiationException e) {
 138  0
             throw new PicoInvocationTargetInitializationException(e);
 139   
         } catch (IllegalAccessException e) {
 140  0
             throw new PicoInvocationTargetInitializationException(e);
 141   
         } finally {
 142  19
             instantiating = false;
 143   
         }
 144   
     }
 145   
 
 146  17
     private void initializeSetterAndTypeLists() {
 147  17
         setters = new ArrayList();
 148  17
         setterNames = new ArrayList();
 149  17
         final List typeList = new ArrayList();
 150  17
         final Method[] methods = getComponentImplementation().getMethods();
 151  17
         for (int i = 0; i < methods.length; i++) {
 152  228
             final Method method = methods[i];
 153  228
             final Class[] parameterTypes = method.getParameterTypes();
 154   
             // We're only interested if there is only one parameter and the method name is bean-style.
 155  228
             if (parameterTypes.length == 1) {
 156  68
                 String methodName = method.getName();   
 157  68
                 boolean isBeanStyle = methodName.length() >= 4 && methodName.startsWith("set") && Character.isUpperCase(methodName.charAt(3));
 158  68
                 if (isBeanStyle) {
 159  34
                     String attribute = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4); 
 160  34
                     setters.add(method);
 161  34
                     setterNames.add(attribute);
 162  34
                     typeList.add(parameterTypes[0]);
 163   
                 }
 164   
             }
 165   
         }
 166  17
         setterTypes = (Class[])typeList.toArray(new Class[0]);
 167   
     }
 168   
 }
 169