Clover coverage report - picocontainer - 1.2-beta-1
Coverage timestamp: Sun May 29 2005 14:29:04 BST
file stats: LOC: 173   Methods: 8
NCLOC: 110   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
BasicComponentParameter.java 96.9% 100% 100% 98.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.Parameter;
 14    import org.picocontainer.PicoContainer;
 15    import org.picocontainer.PicoInstantiationException;
 16    import org.picocontainer.PicoIntrospectionException;
 17    import org.picocontainer.PicoVisitor;
 18   
 19    import java.io.Serializable;
 20    import java.lang.reflect.Field;
 21    import java.util.Arrays;
 22    import java.util.HashSet;
 23    import java.util.List;
 24    import java.util.Iterator;
 25   
 26    /**
 27    * A BasicComponentParameter should be used to pass in a particular component as argument to a
 28    * different component's constructor. This is particularly useful in cases where several
 29    * components of the same type have been registered, but with a different key. Passing a
 30    * ComponentParameter as a parameter when registering a component will give PicoContainer a hint
 31    * about what other component to use in the constructor. This Parameter will never resolve
 32    * against a collecting type, that is not directly registered in the PicoContainer itself.
 33    *
 34    * @author Jon Tirsén
 35    * @author Aslak Hellesøy
 36    * @author Jörg Schaible
 37    * @author Thomas Heller
 38    * @version $Revision: 1944 $
 39    */
 40    public class BasicComponentParameter
 41    implements Parameter, Serializable {
 42   
 43    /**
 44    * <code>BASIC_DEFAULT</code> is an instance of BasicComponentParameter using the default constructor.
 45    */
 46    public static final BasicComponentParameter BASIC_DEFAULT = new BasicComponentParameter();
 47   
 48    private Object componentKey;
 49   
 50    /**
 51    * Expect a parameter matching a component of a specific key.
 52    *
 53    * @param componentKey the key of the desired component
 54    */
 55  266 public BasicComponentParameter(Object componentKey) {
 56  266 this.componentKey = componentKey;
 57    }
 58   
 59    /**
 60    * Expect any paramter of the appropriate type.
 61    */
 62  70 public BasicComponentParameter() {
 63    }
 64   
 65    /**
 66    * Check wether the given Parameter can be statisfied by the container.
 67    *
 68    * @return <code>true</code> if the Parameter can be verified.
 69    * @see org.picocontainer.Parameter#isResolvable(org.picocontainer.PicoContainer,
 70    * org.picocontainer.ComponentAdapter, java.lang.Class)
 71    */
 72  1648 public boolean isResolvable(PicoContainer container, ComponentAdapter adapter, Class expectedType) {
 73  1648 return resolveAdapter(container, adapter, expectedType) != null;
 74    }
 75   
 76  464 public Object resolveInstance(PicoContainer container, ComponentAdapter adapter, Class expectedType)
 77    throws PicoInstantiationException {
 78  464 final ComponentAdapter componentAdapter = resolveAdapter(container, adapter, expectedType);
 79  464 if (componentAdapter != null) {
 80  394 return container.getComponentInstance(componentAdapter.getComponentKey());
 81    }
 82  70 return null;
 83    }
 84   
 85  16 public void verify(PicoContainer container, ComponentAdapter adapter, Class expectedType) throws PicoIntrospectionException {
 86  16 final ComponentAdapter componentAdapter = resolveAdapter(container, adapter, expectedType);
 87  16 if (componentAdapter == null) {
 88  2 final HashSet set = new HashSet();
 89  2 set.add(Arrays.asList(new Class[] {expectedType}));
 90  2 throw new UnsatisfiableDependenciesException(adapter, set);
 91    }
 92  14 componentAdapter.verify(container);
 93    }
 94   
 95    /**
 96    * Visit the current {@link Parameter}.
 97    *
 98    * @see org.picocontainer.Parameter#accept(org.picocontainer.PicoVisitor)
 99    */
 100  24 public void accept(final PicoVisitor visitor) {
 101  24 visitor.visitParameter(this);
 102    }
 103   
 104  2128 private ComponentAdapter resolveAdapter(PicoContainer container, ComponentAdapter adapter, Class expectedType) {
 105   
 106  2128 final ComponentAdapter result = getTargetAdapter(container, expectedType,adapter);
 107  2114 if (result == null) {
 108  1186 return null;
 109    }
 110   
 111  928 if (!expectedType.isAssignableFrom(result.getComponentImplementation())) {
 112    // check for primitive value
 113  20 if (expectedType.isPrimitive()) {
 114  6 try {
 115  6 final Field field = result.getComponentImplementation().getField("TYPE");
 116  4 final Class type = (Class) field.get(result.getComponentInstance(null));
 117  4 if (expectedType.isAssignableFrom(type)) {
 118  4 return result;
 119    }
 120    } catch (NoSuchFieldException e) {
 121    } catch (IllegalArgumentException e) {
 122    } catch (IllegalAccessException e) {
 123    } catch (ClassCastException e) {
 124    }
 125    }
 126  16 return null;
 127    }
 128  908 return result;
 129    }
 130   
 131  2128 private ComponentAdapter getTargetAdapter(PicoContainer container, Class expectedType, ComponentAdapter excludeAdapter) {
 132  2128 if (componentKey != null) {
 133    // key tells us where to look so we follow
 134  54 return container.getComponentAdapter(componentKey);
 135  2074 } else if(excludeAdapter == null) {
 136  2 return container.getComponentAdapterOfType(expectedType);
 137    } else {
 138  2072 Object excludeKey = excludeAdapter.getComponentKey();
 139  2072 ComponentAdapter byKey = container.getComponentAdapter(expectedType);
 140  2072 if(byKey != null ) {
 141  656 if( byKey.getComponentKey().equals(excludeKey)) {
 142  22 return null;
 143    }
 144  634 return byKey;
 145    }
 146  1416 List found = container.getComponentAdaptersOfType(expectedType);
 147  1416 ComponentAdapter exclude = null;
 148  1416 ComponentAdapter work;
 149  1416 for(Iterator iterator = found.iterator(); iterator.hasNext();) {
 150  324 work = (ComponentAdapter) iterator.next();
 151  324 if( work.getComponentKey().equals(excludeKey)) {
 152  94 exclude = work;
 153    }
 154    }
 155  1416 found.remove(exclude);
 156  1416 if(found.size() == 0) {
 157  1200 if( container.getParent() != null) {
 158  68 return container.getParent().getComponentAdapterOfType(expectedType);
 159    } else {
 160  1132 return null;
 161    }
 162  216 } else if(found.size() == 1) {
 163  202 return (ComponentAdapter)found.get(0);
 164    } else {
 165  14 Class[] foundClasses = new Class[found.size()];
 166  14 for (int i = 0; i < foundClasses.length; i++) {
 167  28 foundClasses[i] = ((ComponentAdapter) found.get(i)).getComponentImplementation();
 168    }
 169  14 throw new AmbiguousComponentResolutionException(expectedType, foundClasses);
 170    }
 171    }
 172    }
 173    }