Rev 91 | Rev 93 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | soliveira | 1 | package org.mentacontainer.impl; |
2 | |||
3 | import java.lang.reflect.Constructor; |
||
4 | import java.lang.reflect.Method; |
||
5 | import java.util.HashMap; |
||
6 | import java.util.Iterator; |
||
7 | import java.util.LinkedList; |
||
8 | import java.util.List; |
||
9 | import java.util.Map; |
||
10 | |||
88 | soliveira | 11 | import org.mentacontainer.ConfigurableFactory; |
91 | soliveira | 12 | import org.mentacontainer.Container; |
2 | soliveira | 13 | import org.mentacontainer.util.FindMethod; |
14 | |||
20 | soliveira | 15 | /** |
16 | * A simple implementation of the Component interface. |
||
17 | * |
||
18 | * @author sergio.oliveira.jr@gmail.com |
||
19 | */ |
||
88 | soliveira | 20 | public class ClassFactory implements ConfigurableFactory { |
20 | soliveira | 21 | |
91 | soliveira | 22 | private final Container container; |
23 | |||
20 | soliveira | 24 | private final Class<? extends Object> klass; |
2 | soliveira | 25 | |
26 | private Map<String, Object> props = null; |
||
27 | |||
28 | private List<Object> initValues = null; |
||
29 | |||
91 | soliveira | 30 | private List<Class<? extends Object>> initTypes = null; |
31 | |||
2 | soliveira | 32 | private Constructor<? extends Object> constructor = null; |
33 | |||
34 | private Map<String, Method> cache = null; |
||
35 | |||
88 | soliveira | 36 | public ClassFactory(Class<? extends Object> klass) { |
20 | soliveira | 37 | |
91 | soliveira | 38 | this(null, klass); |
39 | } |
||
40 | |||
41 | public ClassFactory(Container container, Class<? extends Object> klass) { |
||
42 | |||
43 | this.container = container; |
||
44 | |||
2 | soliveira | 45 | this.klass = klass; |
46 | } |
||
47 | |||
84 | soliveira | 48 | @Override |
91 | soliveira | 49 | public ConfigurableFactory addPropertyValue(String name, Object value) { |
86 | soliveira | 50 | |
2 | soliveira | 51 | if (props == null) { |
52 | |||
53 | props = new HashMap<String, Object>(); |
||
54 | |||
55 | cache = new HashMap<String, Method>(); |
||
56 | } |
||
57 | |||
58 | props.put(name, value); |
||
20 | soliveira | 59 | |
60 | return this; |
||
2 | soliveira | 61 | } |
62 | |||
84 | soliveira | 63 | @Override |
91 | soliveira | 64 | public ConfigurableFactory addPropertyDependency(String property, String key) { |
2 | soliveira | 65 | |
91 | soliveira | 66 | if (container == null) throw new IllegalStateException("Cannot set property dependency because factory does not have container!"); |
67 | |||
68 | return addPropertyValue(property, new DependencyKey(key)); |
||
69 | } |
||
70 | |||
71 | @Override |
||
72 | public ConfigurableFactory addInitDependency(String key) { |
||
73 | |||
74 | if (container == null) throw new IllegalStateException("Cannot set constructor dependency because factory does not have container!"); |
||
75 | |||
76 | return addInitValue(new DependencyKey(key), container.getType(key)); |
||
77 | } |
||
78 | |||
79 | private ConfigurableFactory addInitValue(Object value, Class<? extends Object> type) { |
||
80 | |||
2 | soliveira | 81 | if (initValues == null) { |
82 | |||
83 | initValues = new LinkedList<Object>(); |
||
91 | soliveira | 84 | |
85 | initTypes = new LinkedList<Class<? extends Object>>(); |
||
2 | soliveira | 86 | } |
87 | |||
88 | initValues.add(value); |
||
20 | soliveira | 89 | |
91 | soliveira | 90 | initTypes.add(type); |
91 | |||
20 | soliveira | 92 | return this; |
2 | soliveira | 93 | } |
94 | |||
91 | soliveira | 95 | @Override |
96 | public ConfigurableFactory addInitValue(Object value) { |
||
2 | soliveira | 97 | |
91 | soliveira | 98 | return addInitValue(value, value.getClass()); |
99 | } |
||
100 | |||
101 | @Override |
||
92 | soliveira | 102 | public ConfigurableFactory addInitPrimitive(Object value) { |
91 | soliveira | 103 | |
92 | soliveira | 104 | Class<? extends Object> primitive = getPrimitiveFrom(value); |
91 | soliveira | 105 | |
92 | soliveira | 106 | if (primitive == null) throw new IllegalArgumentException("Value is not a primitive: " + value); |
91 | soliveira | 107 | |
92 | soliveira | 108 | return addInitValue(value, primitive); |
91 | soliveira | 109 | } |
110 | |||
92 | soliveira | 111 | private List<Class<? extends Object>> convertToPrimitives(List<Class<? extends Object>> list) { |
91 | soliveira | 112 | |
92 | soliveira | 113 | Iterator<Class<? extends Object>> iter = list.iterator(); |
91 | soliveira | 114 | |
92 | soliveira | 115 | List<Class<? extends Object>> results = new LinkedList<Class<? extends Object>>(); |
91 | soliveira | 116 | |
92 | soliveira | 117 | while(iter.hasNext()) { |
118 | |||
119 | Class<? extends Object> klass = iter.next(); |
||
120 | |||
121 | Class<? extends Object> primitive = getPrimitiveFrom(klass); |
||
122 | |||
123 | if (primitive != null) { |
||
124 | |||
125 | results.add(primitive); |
||
126 | |||
127 | } else { |
||
128 | |||
129 | results.add(klass); |
||
130 | } |
||
131 | } |
||
91 | soliveira | 132 | |
92 | soliveira | 133 | return results; |
91 | soliveira | 134 | } |
135 | |||
136 | private Class<? extends Object>[] getClasses(List<Class<? extends Object>> values) { |
||
137 | |||
2 | soliveira | 138 | Class<? extends Object>[] types = (Class<? extends Object>[]) new Class[values.size()]; |
139 | |||
91 | soliveira | 140 | return values.toArray(types); |
2 | soliveira | 141 | } |
142 | |||
143 | private Object [] getValues(List<Object> values) throws InstantiationException { |
||
144 | |||
145 | Object [] array = new Object[values.size()]; |
||
146 | |||
147 | int index = 0; |
||
148 | |||
149 | Iterator<Object> iter = values.iterator(); |
||
150 | |||
151 | while(iter.hasNext()) { |
||
152 | |||
153 | Object obj = iter.next(); |
||
91 | soliveira | 154 | |
155 | if (obj instanceof DependencyKey) { |
||
156 | |||
157 | DependencyKey dk = (DependencyKey) obj; |
||
158 | |||
159 | array[index++] = container.get(dk.getKey()); |
||
160 | |||
161 | } else { |
||
2 | soliveira | 162 | |
91 | soliveira | 163 | array[index++] = obj; |
164 | } |
||
2 | soliveira | 165 | } |
166 | |||
167 | return array; |
||
168 | } |
||
169 | |||
170 | /* |
||
171 | * Use reflection to set a property in the bean |
||
172 | */ |
||
40 | soliveira | 173 | private void setValue(Object bean, String name, Object value) { |
2 | soliveira | 174 | |
175 | try { |
||
20 | soliveira | 176 | |
2 | soliveira | 177 | StringBuffer sb = new StringBuffer(30); |
178 | sb.append("set"); |
||
179 | sb.append(name.substring(0,1).toUpperCase()); |
||
20 | soliveira | 180 | |
2 | soliveira | 181 | if (name.length() > 1) sb.append(name.substring(1)); |
182 | |||
183 | String methodName = sb.toString(); |
||
184 | |||
185 | if (!cache.containsKey(name)) { |
||
20 | soliveira | 186 | |
2 | soliveira | 187 | Method m = null; |
20 | soliveira | 188 | |
2 | soliveira | 189 | try { |
20 | soliveira | 190 | |
2 | soliveira | 191 | m = FindMethod.getMethod(klass, methodName, new Class[] { value.getClass() }); |
20 | soliveira | 192 | |
2 | soliveira | 193 | } catch(Exception e) { |
20 | soliveira | 194 | |
2 | soliveira | 195 | // try primitive... |
20 | soliveira | 196 | |
2 | soliveira | 197 | Class<? extends Object> primitive = getPrimitiveFrom(value); |
20 | soliveira | 198 | |
2 | soliveira | 199 | if (primitive != null) { |
20 | soliveira | 200 | |
2 | soliveira | 201 | try { |
20 | soliveira | 202 | |
2 | soliveira | 203 | m = klass.getMethod(methodName, new Class[] { primitive }); |
20 | soliveira | 204 | |
2 | soliveira | 205 | } catch(Exception ex) { |
206 | // not found! |
||
207 | } |
||
208 | } |
||
209 | |||
210 | if (m == null) { |
||
20 | soliveira | 211 | |
91 | soliveira | 212 | throw new InstantiationException("Cannot find method for property: " + name); |
2 | soliveira | 213 | } |
214 | } |
||
215 | |||
216 | if (m != null) { |
||
20 | soliveira | 217 | |
2 | soliveira | 218 | cache.put(name, m); |
20 | soliveira | 219 | |
2 | soliveira | 220 | m.setAccessible(true); |
221 | } |
||
222 | } |
||
223 | |||
224 | Method m = cache.get(name); |
||
20 | soliveira | 225 | |
2 | soliveira | 226 | if (m != null) { |
20 | soliveira | 227 | |
2 | soliveira | 228 | m.invoke(bean, new Object[] { value }); |
229 | } |
||
20 | soliveira | 230 | |
2 | soliveira | 231 | } catch(Exception e) { |
20 | soliveira | 232 | |
40 | soliveira | 233 | throw new RuntimeException("Error trying to set a property with reflection: " + name, e); |
2 | soliveira | 234 | } |
235 | } |
||
236 | |||
237 | private static Class<? extends Object> getPrimitiveFrom(Object w) { |
||
238 | if (w instanceof Boolean) { return Boolean.TYPE; } |
||
239 | else if (w instanceof Byte) { return Byte.TYPE; } |
||
240 | else if (w instanceof Short) { return Short.TYPE; } |
||
241 | else if (w instanceof Character) { return Character.TYPE; } |
||
242 | else if (w instanceof Integer) { return Integer.TYPE; } |
||
243 | else if (w instanceof Long) { return Long.TYPE; } |
||
244 | else if (w instanceof Float) { return Float.TYPE; } |
||
245 | else if (w instanceof Double) { return Double.TYPE; } |
||
246 | return null; |
||
92 | soliveira | 247 | } |
2 | soliveira | 248 | |
92 | soliveira | 249 | private static Class<? extends Object> getPrimitiveFrom(Class<? extends Object> klass) { |
250 | if (klass.equals(Boolean.class)) { return Boolean.TYPE; } |
||
251 | else if (klass.equals(Byte.class)) { return Byte.TYPE; } |
||
252 | else if (klass.equals(Short.class)) { return Short.TYPE; } |
||
253 | else if (klass.equals(Character.class)) { return Character.TYPE; } |
||
254 | else if (klass.equals(Integer.class)) { return Integer.TYPE; } |
||
255 | else if (klass.equals(Long.class)) { return Long.TYPE; } |
||
256 | else if (klass.equals(Float.class)) { return Float.TYPE; } |
||
257 | else if (klass.equals(Double.class)) { return Double.TYPE; } |
||
258 | return null; |
||
259 | } |
||
260 | |||
84 | soliveira | 261 | @Override |
41 | soliveira | 262 | public <T> T getInstance() { |
20 | soliveira | 263 | |
2 | soliveira | 264 | Object obj = null; |
20 | soliveira | 265 | |
2 | soliveira | 266 | if (initValues != null && initValues.size() > 0) { |
20 | soliveira | 267 | |
2 | soliveira | 268 | if (constructor == null) { |
20 | soliveira | 269 | |
2 | soliveira | 270 | try { |
20 | soliveira | 271 | |
91 | soliveira | 272 | constructor = klass.getConstructor(getClasses(initTypes)); |
20 | soliveira | 273 | |
2 | soliveira | 274 | } catch(Exception e) { |
20 | soliveira | 275 | |
92 | soliveira | 276 | // try primitives... |
277 | |||
278 | try { |
||
279 | |||
280 | constructor = klass.getConstructor(getClasses(convertToPrimitives(initTypes))); |
||
281 | |||
282 | } catch(Exception ee) { |
||
283 | |||
284 | throw new RuntimeException("Cannot find a constructor for class: " + klass); |
||
285 | } |
||
2 | soliveira | 286 | } |
287 | } |
||
20 | soliveira | 288 | |
2 | soliveira | 289 | try { |
20 | soliveira | 290 | |
2 | soliveira | 291 | obj = constructor.newInstance(getValues(initValues)); |
20 | soliveira | 292 | |
2 | soliveira | 293 | } catch(Exception e) { |
20 | soliveira | 294 | |
40 | soliveira | 295 | throw new RuntimeException("Cannot create instance from constructor: " + constructor, e); |
2 | soliveira | 296 | } |
20 | soliveira | 297 | |
2 | soliveira | 298 | } else { |
20 | soliveira | 299 | |
2 | soliveira | 300 | try { |
20 | soliveira | 301 | |
2 | soliveira | 302 | obj = klass.newInstance(); |
20 | soliveira | 303 | |
2 | soliveira | 304 | } catch(Exception e) { |
20 | soliveira | 305 | |
40 | soliveira | 306 | throw new RuntimeException("Cannot create instance from class: " + klass, e); |
2 | soliveira | 307 | } |
308 | } |
||
20 | soliveira | 309 | |
2 | soliveira | 310 | if (props != null && props.size() > 0) { |
20 | soliveira | 311 | |
2 | soliveira | 312 | Iterator<String> iter = props.keySet().iterator(); |
20 | soliveira | 313 | |
2 | soliveira | 314 | while(iter.hasNext()) { |
20 | soliveira | 315 | |
2 | soliveira | 316 | String name = iter.next(); |
20 | soliveira | 317 | |
2 | soliveira | 318 | Object value = props.get(name); |
20 | soliveira | 319 | |
91 | soliveira | 320 | if (value instanceof DependencyKey) { |
321 | |||
322 | DependencyKey dk = (DependencyKey) value; |
||
323 | |||
324 | value = container.get(dk.getKey()); |
||
325 | } |
||
326 | |||
2 | soliveira | 327 | setValue(obj, name, value); |
328 | } |
||
329 | } |
||
20 | soliveira | 330 | |
41 | soliveira | 331 | return (T) obj; |
2 | soliveira | 332 | } |
91 | soliveira | 333 | |
334 | private static class DependencyKey { |
||
335 | |||
336 | private String key; |
||
337 | |||
338 | public DependencyKey(String key) { this.key = key; } |
||
339 | |||
340 | private String getKey() { return key; } |
||
341 | } |
||
342 | |||
343 | @Override |
||
344 | public Class<? extends Object> getType() { |
||
345 | return klass; |
||
346 | } |
||
2 | soliveira | 347 | } |