1 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.PicoInitializationException; 16 import org.picocontainer.PicoInstantiationException; 17 import org.picocontainer.PicoIntrospectionException; 18 import org.picocontainer.PicoVisitor; 19 20 import java.io.Serializable ; 21 import java.lang.reflect.Array ; 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.HashMap ; 25 import java.util.HashSet ; 26 import java.util.Iterator ; 27 import java.util.List ; 28 import java.util.Map ; 29 import java.util.Set ; 30 import java.util.SortedMap ; 31 import java.util.SortedSet ; 32 import java.util.TreeMap ; 33 import java.util.TreeSet ; 34 35 36 46 public class CollectionComponentParameter 47 implements Parameter, Serializable { 48 49 52 public static final CollectionComponentParameter ARRAY = new CollectionComponentParameter(); 53 57 public static final CollectionComponentParameter ARRAY_ALLOW_EMPTY = new CollectionComponentParameter(true); 58 59 private final boolean emptyCollection; 60 private final Class componentKeyType; 61 private final Class componentValueType; 62 63 67 public CollectionComponentParameter() { 68 this(false); 69 } 70 71 77 public CollectionComponentParameter(boolean emptyCollection) { 78 this(Void.TYPE, emptyCollection); 79 } 80 81 89 public CollectionComponentParameter(Class componentValueType, boolean emptyCollection) { 90 this(Object .class, componentValueType, emptyCollection); 91 } 92 93 102 public CollectionComponentParameter(Class componentKeyType, Class componentValueType, boolean emptyCollection) { 103 this.emptyCollection = emptyCollection; 104 this.componentKeyType = componentKeyType; 105 this.componentValueType = componentValueType; 106 } 107 108 120 public Object resolveInstance(PicoContainer container, ComponentAdapter adapter, Class expectedType) 121 throws PicoInstantiationException { 122 Object result = null; 124 final Class collectionType = getCollectionType(expectedType); 125 if (collectionType != null) { 126 final Map adapterMap = getMatchingComponentAdapters(container, adapter, componentKeyType, getValueType(expectedType)); 127 if (Array .class.isAssignableFrom(collectionType)) { 128 result = getArrayInstance(container, expectedType, adapterMap); 129 } else if (Map .class.isAssignableFrom(collectionType)) { 130 result = getMapInstance(container, expectedType, adapterMap); 131 } else if (Collection .class.isAssignableFrom(collectionType)) { 132 result = getCollectionInstance(container, expectedType, adapterMap); 133 } else { 134 throw new PicoIntrospectionException(expectedType.getName() + " is not a collective type"); 135 } 136 } 137 return result; 138 } 139 140 152 public boolean isResolvable(PicoContainer container, ComponentAdapter adapter, Class expectedType) { 153 final Class collectionType = getCollectionType(expectedType); 154 final Class valueType = getValueType(expectedType); 155 return collectionType != null && (emptyCollection || getMatchingComponentAdapters(container, adapter, componentKeyType, valueType).size() > 0); 156 } 157 158 169 public void verify(PicoContainer container, ComponentAdapter adapter, Class expectedType) throws PicoIntrospectionException { 170 final Class collectionType = getCollectionType(expectedType); 171 if (collectionType != null) { 172 final Class valueType = getValueType(expectedType); 173 final Collection componentAdapters = getMatchingComponentAdapters(container, adapter, componentKeyType, valueType).values(); 174 if (componentAdapters.isEmpty()) { 175 if (!emptyCollection) { 176 throw new PicoIntrospectionException(expectedType.getName() 177 + " not resolvable, no components of type " 178 + getValueType(expectedType).getName() 179 + " available"); 180 } 181 } else { 182 for (final Iterator iter = componentAdapters.iterator(); iter.hasNext();) { 183 final ComponentAdapter componentAdapter = (ComponentAdapter) iter.next(); 184 componentAdapter.verify(container); 185 } 186 } 187 } else { 188 throw new PicoIntrospectionException(expectedType.getName() + " is not a collective type"); 189 } 190 return; 191 } 192 193 198 public void accept(final PicoVisitor visitor) { 199 visitor.visitParameter(this); 200 } 201 202 208 protected boolean evaluate(final ComponentAdapter adapter) { 209 return adapter != null; } 211 212 220 protected Map getMatchingComponentAdapters(PicoContainer container, ComponentAdapter adapter, Class keyType, Class valueType) { 221 final Map adapterMap = new HashMap (); 222 final PicoContainer parent = container.getParent(); 223 if (parent != null) { 224 adapterMap.putAll(getMatchingComponentAdapters(parent, adapter, keyType, valueType)); 225 } 226 final Collection allAdapters = container.getComponentAdapters(); 227 for (final Iterator iter = allAdapters.iterator(); iter.hasNext();) { 228 final ComponentAdapter componentAdapter = (ComponentAdapter) iter.next(); 229 adapterMap.remove(componentAdapter.getComponentKey()); 230 } 231 final List adapterList = container.getComponentAdaptersOfType(valueType); 232 for (final Iterator iter = adapterList.iterator(); iter.hasNext();) { 233 final ComponentAdapter componentAdapter = (ComponentAdapter) iter.next(); 234 final Object key = componentAdapter.getComponentKey(); 235 if (adapter != null && key.equals(adapter.getComponentKey())) { 236 continue; 237 } 238 if (keyType.isAssignableFrom(key.getClass()) && evaluate(componentAdapter)) { 239 adapterMap.put(key, componentAdapter); 240 } 241 } 242 return adapterMap; 243 } 244 245 private Class getCollectionType(final Class collectionType) { 246 Class collectionClass = null; 247 if (collectionType.isArray()) { 248 collectionClass = Array .class; 249 } else if (Map .class.isAssignableFrom(collectionType)) { 250 collectionClass = Map .class; 251 } else if (Collection .class.isAssignableFrom(collectionType)) { 252 collectionClass = Collection .class; 253 } 254 return collectionClass; 255 } 256 257 private Class getValueType(final Class collectionType) { 258 Class valueType = componentValueType; 259 if (collectionType.isArray()) { 260 valueType = collectionType.getComponentType(); 261 } 262 return valueType; 263 } 264 265 private Object [] getArrayInstance(final PicoContainer container, final Class expectedType, final Map adapterList) { 266 final Object [] result = (Object []) Array.newInstance(expectedType.getComponentType(), adapterList.size()); 267 int i = 0; 268 for (final Iterator iterator = adapterList.values().iterator(); iterator.hasNext();) { 269 final ComponentAdapter componentAdapter = (ComponentAdapter) iterator.next(); 270 result[i] = container.getComponentInstance(componentAdapter.getComponentKey()); 271 i++; 272 } 273 return result; 274 } 275 276 private Collection getCollectionInstance(final PicoContainer container, final Class expectedType, final Map adapterList) { 277 Class collectionType = expectedType; 278 if (collectionType.isInterface()) { 279 if (List .class.isAssignableFrom(collectionType)) { 281 collectionType = ArrayList .class; 282 } else if (SortedSet .class.isAssignableFrom(collectionType)) { 287 collectionType = TreeSet .class; 288 } else if (Set .class.isAssignableFrom(collectionType)) { 289 collectionType = HashSet .class; 290 } else if (Collection .class.isAssignableFrom(collectionType)) { 291 collectionType = ArrayList .class; 292 } 293 } 294 try { 295 Collection result = (Collection ) collectionType.newInstance(); 296 for (final Iterator iterator = adapterList.values().iterator(); iterator.hasNext();) { 297 final ComponentAdapter componentAdapter = (ComponentAdapter) iterator.next(); 298 result.add(container.getComponentInstance(componentAdapter.getComponentKey())); 299 } 300 return result; 301 } catch (InstantiationException e) { 302 throw new PicoInitializationException(e); 304 } catch (IllegalAccessException e) { 306 throw new PicoInitializationException(e); 308 } 310 } 311 312 private Map getMapInstance(final PicoContainer container, final Class expectedType, final Map adapterList) { 313 Class collectionType = expectedType; 314 if (collectionType.isInterface()) { 315 if (SortedMap .class.isAssignableFrom(collectionType)) { 317 collectionType = TreeMap .class; 318 } else if (Map .class.isAssignableFrom(collectionType)) { 321 collectionType = HashMap .class; 322 } 323 } 324 try { 325 Map result = (Map ) collectionType.newInstance(); 326 for (final Iterator iterator = adapterList.entrySet().iterator(); iterator.hasNext();) { 327 final Map.Entry entry = (Map.Entry ) iterator.next(); 328 final Object key = entry.getKey(); 329 final ComponentAdapter componentAdapter = (ComponentAdapter) entry.getValue(); 330 result.put(key, container.getComponentInstance(key)); 331 } 332 return result; 333 } catch (InstantiationException e) { 334 throw new PicoInitializationException(e); 336 } catch (IllegalAccessException e) { 338 throw new PicoInitializationException(e); 340 } 342 } 343 344 } 345 | Popular Tags |