001 /***************************************************************************** 002 * Copyright (C) PicoContainer Organization. All rights reserved. * 003 * ------------------------------------------------------------------------- * 004 * The software in this package is published under the terms of the BSD * 005 * style license a copy of which has been included with this distribution in * 006 * the LICENSE.txt file. * 007 * * 008 * Original code by * 009 *****************************************************************************/ 010 package org.picocontainer.defaults; 011 012 import org.picocontainer.ComponentAdapter; 013 import org.picocontainer.Parameter; 014 import org.picocontainer.PicoContainer; 015 import org.picocontainer.PicoVisitor; 016 017 018 /** 019 * A ComponentParameter should be used to pass in a particular component as argument to a 020 * different component's constructor. This is particularly useful in cases where several 021 * components of the same type have been registered, but with a different key. Passing a 022 * ComponentParameter as a parameter when registering a component will give PicoContainer a hint 023 * about what other component to use in the constructor. Collecting parameter types are 024 * supported for {@link java.lang.reflect.Array},{@link java.util.Collection}and 025 * {@link java.util.Map}. 026 * 027 * @author Jon Tirsén 028 * @author Aslak Hellesøy 029 * @author Jörg Schaible 030 * @author Thomas Heller 031 * @version $Revision: 2285 $ 032 */ 033 public class ComponentParameter 034 extends BasicComponentParameter { 035 036 /** 037 * <code>DEFAULT</code> is an instance of ComponentParameter using the default constructor. 038 */ 039 public static final ComponentParameter DEFAULT = new ComponentParameter(); 040 /** 041 * Use <code>ARRAY</code> as {@link Parameter}for an Array that must have elements. 042 */ 043 public static final ComponentParameter ARRAY = new ComponentParameter(false); 044 /** 045 * Use <code>ARRAY_ALLOW_EMPTY</code> as {@link Parameter}for an Array that may have no 046 * elements. 047 */ 048 public static final ComponentParameter ARRAY_ALLOW_EMPTY = new ComponentParameter(true); 049 050 private final Parameter collectionParameter; 051 052 /** 053 * Expect a parameter matching a component of a specific key. 054 * 055 * @param componentKey the key of the desired component 056 */ 057 public ComponentParameter(Object componentKey) { 058 this(componentKey, null); 059 } 060 061 /** 062 * Expect any scalar paramter of the appropriate type or an {@link java.lang.reflect.Array}. 063 */ 064 public ComponentParameter() { 065 this(false); 066 } 067 068 /** 069 * Expect any scalar paramter of the appropriate type or an {@link java.lang.reflect.Array}. 070 * Resolve the parameter even if no compoennt is of the array's component type. 071 * 072 * @param emptyCollection <code>true</code> allows an Array to be empty 073 * @since 1.1 074 */ 075 public ComponentParameter(boolean emptyCollection) { 076 this(null, emptyCollection ? CollectionComponentParameter.ARRAY_ALLOW_EMPTY : CollectionComponentParameter.ARRAY); 077 } 078 079 /** 080 * Expect any scalar paramter of the appropriate type or the collecting type 081 * {@link java.lang.reflect.Array},{@link java.util.Collection}or {@link java.util.Map}. 082 * The components in the collection will be of the specified type. 083 * 084 * @param componentValueType the component's type (ignored for an Array) 085 * @param emptyCollection <code>true</code> allows the collection to be empty 086 * @since 1.1 087 */ 088 public ComponentParameter(Class componentValueType, boolean emptyCollection) { 089 this(null, new CollectionComponentParameter(componentValueType, emptyCollection)); 090 } 091 092 /** 093 * Expect any scalar paramter of the appropriate type or the collecting type 094 * {@link java.lang.reflect.Array},{@link java.util.Collection}or {@link java.util.Map}. 095 * The components in the collection will be of the specified type and their adapter's key 096 * must have a particular type. 097 * 098 * @param componentKeyType the component adapter's key type 099 * @param componentValueType the component's type (ignored for an Array) 100 * @param emptyCollection <code>true</code> allows the collection to be empty 101 * @since 1.1 102 */ 103 public ComponentParameter(Class componentKeyType, Class componentValueType, boolean emptyCollection) { 104 this(null, new CollectionComponentParameter(componentKeyType, componentValueType, emptyCollection)); 105 } 106 107 private ComponentParameter(Object componentKey, Parameter collectionParameter) { 108 super(componentKey); 109 this.collectionParameter = collectionParameter; 110 } 111 112 public Object resolveInstance(PicoContainer container, ComponentAdapter adapter, Class expectedType) { 113 // type check is done in isResolvable 114 Object result = super.resolveInstance(container, adapter, expectedType); 115 if (result == null && collectionParameter != null) { 116 result = collectionParameter.resolveInstance(container, adapter, expectedType); 117 } 118 return result; 119 } 120 121 public boolean isResolvable(PicoContainer container, ComponentAdapter adapter, Class expectedType) { 122 if (!super.isResolvable(container, adapter, expectedType)) { 123 if (collectionParameter != null) { 124 return collectionParameter.isResolvable(container, adapter, expectedType); 125 } 126 return false; 127 } 128 return true; 129 } 130 131 public void verify(PicoContainer container, ComponentAdapter adapter, Class expectedType) { 132 try { 133 super.verify(container, adapter, expectedType); 134 } catch (UnsatisfiableDependenciesException e) { 135 if (collectionParameter != null) { 136 collectionParameter.verify(container, adapter, expectedType); 137 return; 138 } 139 throw e; 140 } 141 } 142 143 /** 144 * Accept the visitor for the current {@link Parameter}. If internally a 145 * {@link CollectionComponentParameter}is used, it is visited also. 146 * 147 * @see org.picocontainer.defaults.BasicComponentParameter#accept(org.picocontainer.PicoVisitor) 148 */ 149 public void accept(PicoVisitor visitor) { 150 super.accept(visitor); 151 if (collectionParameter != null) { 152 collectionParameter.accept(visitor); 153 } 154 } 155 }