1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 package org.objectledge.pico;
30
31 import java.lang.reflect.Array;
32 import java.lang.reflect.Constructor;
33 import java.util.Arrays;
34 import java.util.Collection;
35
36 import org.picocontainer.ComponentAdapter;
37 import org.picocontainer.Parameter;
38 import org.picocontainer.PicoContainer;
39 import org.picocontainer.PicoException;
40 import org.picocontainer.PicoInitializationException;
41 import org.picocontainer.PicoIntrospectionException;
42 import org.picocontainer.PicoVisitor;
43
44 /***
45 * Allows hinting the component's constructor arguments of aggregated types.
46 *
47 * <p>
48 * Both Java arrays and <code>java.util.Collection</code> objects are supported.
49 * The elements of the sequence are <code>org.picocontainer.Parameter</code> objects
50 * - they may resolve to constants, component references, or nested sequences.
51 * </p>
52 *
53 * @author <a href="Rafal.Krzewski">rafal@caltha.pl</a>
54 * @version $Id: SequenceParameter.java,v 1.6 2005/07/07 08:30:04 zwierzem Exp $
55 */
56 public class SequenceParameter implements Parameter
57 {
58 private Parameter[] elements;
59 private Class implClass;
60
61 /***
62 * Creates a sequence parameter.
63 *
64 * @param elements the sequence elements.
65 * @param implClass collection implementation class, may be null.
66 */
67 public SequenceParameter(Parameter[] elements, Class implClass)
68 {
69 this.elements = elements;
70 this.implClass = implClass;
71 }
72
73 /***
74 * {@inheritDoc}
75 */
76 public Object resolveInstance(PicoContainer container, ComponentAdapter adapter,
77 Class expectedType)
78 throws PicoInitializationException
79 {
80 Class elementType = getElementType(expectedType);
81 Object[] items = new Object[elements.length];
82 for(int i = 0; i < elements.length; i++)
83 {
84 items[i] = elements[i].resolveInstance(container, adapter, elementType);
85 }
86 if(expectedType.getComponentType() != null)
87 {
88 return toArray(items, expectedType);
89 }
90 if(Collection.class.isAssignableFrom(expectedType))
91 {
92 if(implClass != null)
93 {
94 return toCollection(items, implClass);
95 }
96 else
97 {
98 return toCollection(items, expectedType);
99 }
100 }
101 throw new PicoIntrospectionException("not a collection nor array type");
102 }
103
104 /***
105 * {@inheritDoc}
106 */
107 public boolean isResolvable(PicoContainer container, ComponentAdapter adapter,
108 Class expectedType)
109 {
110 try
111 {
112 Class elementType = getElementType(expectedType);
113 for(Parameter element : elements)
114 {
115 if(!element.isResolvable(container, adapter, elementType))
116 {
117 return false;
118 }
119 }
120 return true;
121 }
122 catch(PicoIntrospectionException e)
123 {
124
125 return false;
126 }
127 }
128
129 /***
130 * {@inheritDoc}
131 */
132 public void verify(PicoContainer container, ComponentAdapter adapter, Class expectedType)
133 throws PicoIntrospectionException
134 {
135 Class elementType = getElementType(expectedType);
136 for(Parameter element : elements)
137 {
138 element.verify(container, adapter, expectedType);
139 }
140 }
141
142 /***
143 * {@inheritDoc}
144 */
145 public void accept(PicoVisitor visitor)
146 {
147 visitor.visitParameter(this);
148 for(Parameter element : elements)
149 {
150 visitor.visitParameter(element);
151 }
152 }
153
154 private Class getElementType(Class expectedType)
155 {
156 if(expectedType.getComponentType() != null)
157 {
158 return expectedType.getComponentType();
159 }
160 if(Collection.class.isAssignableFrom(expectedType))
161 {
162
163
164
165
166 return Object.class;
167 }
168 throw new PicoIntrospectionException("not a collection nor array type");
169 }
170
171 private Object toArray(Object[] source, Class targetType)
172 {
173 Object target = Array.newInstance(targetType.getComponentType(), source.length);
174 System.arraycopy(source, 0, target, 0, source.length);
175 return target;
176 }
177
178 private Object toCollection(Object[] source, Class targetType)
179 {
180 Collection target;
181 try
182 {
183 try
184 {
185 Constructor ctor = targetType.getConstructor(new Class[] { Integer.TYPE });
186 target = (Collection)ctor.newInstance(new Object[] { new Integer(source.length) });
187 }
188 catch(NoSuchMethodException e)
189 {
190 try
191 {
192 Constructor ctor = targetType.getConstructor(new Class[0]);
193 target = (Collection)ctor.newInstance(new Object[0]);
194 }
195 catch(NoSuchMethodException ee)
196 {
197 throw new CollectionInstantiationException("cannot instantiate Collection "
198 + targetType.getName() + " no supported constructors found", ee);
199 }
200 }
201 }
202 catch(Exception e)
203 {
204 if(e instanceof PicoException)
205 {
206 throw (PicoException)e;
207 }
208 else
209 {
210 throw new CollectionInstantiationException("cannot instantiate Collection "
211 + targetType.getName(), e);
212 }
213 }
214 target.addAll(Arrays.asList(source));
215 return target;
216 }
217 }