1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.org.usurper;
21
22 import java.beans.IntrospectionException;
23 import java.beans.Introspector;
24 import java.beans.PropertyDescriptor;
25 import java.lang.reflect.Constructor;
26 import java.lang.reflect.InvocationTargetException;
27 import java.lang.reflect.Method;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Comparator;
31 import java.util.HashSet;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Set;
35 import java.util.TreeSet;
36
37 import org.org.usurper.handlers.IHandler;
38 import org.org.usurper.handlers.basic.AbstractPropertyTypeHandler;
39 import org.org.usurper.handlers.basic.AbstractSpecificPropertyHandler;
40 import org.org.usurper.handlers.exceptions.NoHandlerDefinedException;
41 import org.org.usurper.model.HandledBeanProperty;
42 import org.org.usurper.model.HandledConstructorArg;
43 import org.org.usurper.model.ITargetDefinition;
44 import org.org.usurper.model.PropertyTypeDefinition;
45 import org.org.usurper.model.SpecificPropertyDefinition;
46 import org.org.usurper.setup.IUsurperGeneratorSetup;
47 import org.org.usurper.setup.ImmutableUsurperGeneratorSetup;
48 import org.org.usurper.setup.UsurperGeneratorSetup;
49 import org.org.usurper.setup.constants.OnMissingHandlers;
50 import org.org.usurper.setup.constants.PropertyWritingMechanism;
51 import org.org.usurper.utils.ReflectionUtils;
52
53
54
55
56
57
58 public class UsurperGenerator<T> {
59
60 private final Class<? extends T> usurpatedClass;
61 private Class<?>[] constructorParameterTypes = new Class<?>[0];
62 private ImmutableUsurperGeneratorSetup setup;
63
64
65
66
67
68
69
70
71
72 public UsurperGenerator(Class<? extends T> usurpatedClass) {
73 this(usurpatedClass, new UsurperGeneratorSetup());
74 }
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 @SuppressWarnings("unchecked")
91 public UsurperGenerator(Class<? extends T> usurpatedClass, OnMissingHandlers onMissingHandlers) {
92 UsurperGeneratorSetup mutableSetup = new UsurperGeneratorSetup();
93 mutableSetup.onMissingHandlers(onMissingHandlers);
94 this.setup = mutableSetup.getImmutable();
95 this.usurpatedClass = usurpatedClass;
96 }
97
98
99
100
101
102
103
104
105
106 public UsurperGenerator(Class<? extends T> usurpatedClass, IUsurperGeneratorSetup usurperGeneratorSetup) {
107 this.replaceSetup(usurperGeneratorSetup);
108 this.usurpatedClass = usurpatedClass;
109 }
110
111
112
113
114
115
116 public T generateUsurper() {
117 T valueObject = null;
118
119 try {
120 valueObject = createInstance();
121
122 if (valueObject == null) {
123 throw new UsurperException("Can not find a usable constructor for bean:" + this.usurpatedClass.getName());
124 }
125
126 PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(this.usurpatedClass).getPropertyDescriptors();
127 for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
128 if (!propertyDescriptor.getName().equals("class")) {
129 String propertyName = propertyDescriptor.getName();
130 Class<?> propertyType = propertyDescriptor.getPropertyType();
131 Method setter = propertyDescriptor.getWriteMethod();
132
133
134
135 if (setter != null) {
136 IHandler handler = getHandler(propertyName, propertyType);
137 Object object = null;
138
139 if (handler == null) {
140 if (this.setup.getOnMissingHandlers().equals(OnMissingHandlers.FAIL)) {
141 throw new NoHandlerDefinedException("No handler defined for property: " + propertyName + "(" + propertyType.getName() + ") in object of type: " + this.usurpatedClass.getName() + ".");
142 }
143 } else {
144 HandledBeanProperty handledBeanProperty = new HandledBeanProperty(valueObject, propertyType, propertyName, this.setup);
145
146 try {
147 object = handler.handle(handledBeanProperty);
148 } catch (NoHandlerDefinedException nhde) {
149
150
151
152
153 if (this.setup.getOnMissingHandlers().equals(OnMissingHandlers.FAIL)) {
154 throw nhde;
155 }
156 }
157 }
158
159 if (object != null) {
160 try {
161 switch (this.setup.getPropertyWritingMechanism()) {
162 case USE_SETTERS:
163 ReflectionUtils.setProperty(valueObject, setter, object);
164 break;
165 case MODIFY_ATTRIBUTES_DIRECTLY:
166 ReflectionUtils.setProperty(valueObject, propertyName, object);
167 break;
168 default:
169 break;
170 }
171
172 } catch (IllegalAccessException e) {
173 throw new UsurperException("Can not access bean property (illegal access):" + this.usurpatedClass.getName() + "." + propertyName, e);
174 } catch (IllegalArgumentException e) {
175 throw new UsurperException("Wrong parameter for the setter of bean property:" + this.usurpatedClass.getName() + "." + propertyName, e);
176 } catch (InvocationTargetException e) {
177 throw new UsurperException("Exception while setting value of bean property:" + this.usurpatedClass.getName() + "." + propertyName, e);
178 } catch (SecurityException e) {
179 throw new UsurperException("Impossible to set the value of bean property:" + this.usurpatedClass.getName() + "." + propertyName, e);
180 } catch (NoSuchFieldException e) {
181 throw new UsurperException("Specified bean property does not exist:" + this.usurpatedClass.getName() + "." + propertyName, e);
182 }
183 }
184 }
185 }
186 }
187
188 } catch (IntrospectionException e) {
189 throw new UsurperException("Can not get Bean Info from bean:" + this.usurpatedClass.getName(), e);
190 }
191
192 return valueObject;
193 }
194
195
196
197
198
199
200
201 private T createInstance() throws SecurityException, UsurperException {
202 T valueObject = null;
203 if (this.constructorParameterTypes.length != 0) {
204 try {
205 Constructor<? extends T> constructor = this.usurpatedClass.getConstructor(this.constructorParameterTypes);
206 valueObject = createInstance(valueObject, constructor);
207 } catch (NoSuchMethodException e) {
208 throw new UsurperException("Can not instantiate bean:" + this.usurpatedClass.getName(), e);
209 }
210 } else {
211 Constructor<? extends T> constructor = choseConstructor(this.usurpatedClass);
212 valueObject = createInstance(valueObject, constructor);
213 }
214 return valueObject;
215 }
216
217 @SuppressWarnings("unchecked")
218 private Constructor<? extends T> choseConstructor(Class<? extends T> usurpatedClass) {
219 Constructor<? extends T> result = null;
220 Set<Constructor> constructors = new TreeSet<Constructor>(new Comparator<Constructor>() {
221 public int compare(Constructor o1, Constructor o2) {
222 int result = 0;
223 result = (o1.getParameterTypes().length > o2.getParameterTypes().length) ? -1 : result;
224 result = (o1.getParameterTypes().length < o2.getParameterTypes().length) ? 1 : result;
225 return -result;
226 }
227 });
228 for (Constructor constructor : Arrays.asList(usurpatedClass.getConstructors())) {
229 constructors.add(constructor);
230 }
231 for (Constructor<? extends T> constructor : constructors) {
232 boolean constructorOk = true;
233 for (Class<?> parameterType : constructor.getParameterTypes()) {
234 IHandler handler = getHandler(parameterType);
235 if (handler == null) {
236 constructorOk = false;
237 break;
238 }
239 }
240 if (constructorOk) {
241 result = constructor;
242 break;
243 }
244 }
245 return result;
246 }
247
248
249
250
251
252
253
254 private T createInstance(T valueObject, Constructor<? extends T> constructor) throws UsurperException {
255 Class<?>[] parameterTypes = constructor.getParameterTypes();
256 Object[] constructorArguments = new Object[parameterTypes.length];
257 int argCounter = 0;
258 for (Class<?> parameterType : parameterTypes) {
259 IHandler handler = getHandler(parameterType);
260 if (handler == null) {
261 break;
262 } else {
263 HandledConstructorArg handledConstructorArg = new HandledConstructorArg(constructor, parameterType, ++argCounter, this.setup);
264 constructorArguments[argCounter - 1] = handler.handle(handledConstructorArg);
265 }
266 }
267 if ((argCounter) == constructorArguments.length && constructorArguments.length == parameterTypes.length) {
268 try {
269 valueObject = constructor.newInstance(constructorArguments);
270 } catch (Exception e) {
271 throw new UsurperException("Can not instantiate bean:" + this.usurpatedClass.getName(), e);
272 }
273 }
274 return valueObject;
275 }
276
277 private IHandler getHandler(Class<?> propertyType) {
278 return getHandler(null, propertyType);
279 }
280
281 private IHandler getHandler(String propertyName, Class<?> propertyType) {
282 IHandler handler;
283 SpecificPropertyDefinition specificPropertyDefinition = new SpecificPropertyDefinition(this.usurpatedClass, propertyName);
284
285 if (propertyType.isArray()) {
286 handler = this.setup.getArrayHandler();
287 } else if (propertyType.isEnum()) {
288 handler = this.setup.getEnumHandler();
289 } else if ((propertyName != null) && (this.setup.hasSpecificPropertyHandler(specificPropertyDefinition))) {
290 handler = this.setup.getSpecificPropertyHandler(specificPropertyDefinition);
291 } else {
292 handler = this.setup.getPropertyTypeHandler(new PropertyTypeDefinition(propertyType));
293 }
294
295 return handler;
296 }
297
298
299
300
301
302
303
304
305 public List<T> generateUsurperList(int number) {
306 List<T> list = new ArrayList<T>();
307 for (int i = 0; i < number; i++) {
308 list.add(generateUsurper());
309 }
310 return list;
311 }
312
313
314
315
316
317
318
319
320 public Set<T> generateUsurperSet(int number) {
321 Set<T> set = new HashSet<T>();
322 for (int i = 0; i < number; i++) {
323 set.add(generateUsurper());
324 }
325 return set;
326 }
327
328
329
330
331
332
333 public void replaceSetup(IUsurperGeneratorSetup usurperGeneratorSetup) {
334 ImmutableUsurperGeneratorSetup immutableUsurperGeneratorSetup = null;
335 if (usurperGeneratorSetup instanceof UsurperGeneratorSetup) {
336 immutableUsurperGeneratorSetup = ((UsurperGeneratorSetup) usurperGeneratorSetup).getImmutable();
337 } else if (usurperGeneratorSetup instanceof ImmutableUsurperGeneratorSetup) {
338 immutableUsurperGeneratorSetup = (ImmutableUsurperGeneratorSetup) usurperGeneratorSetup;
339 } else {
340 throw new IllegalArgumentException(usurperGeneratorSetup.getClass().getName() + " is not a valid setup instance. Valid implementations are:\n\t-" + UsurperGeneratorSetup.class.getName() + "\n\t-" + ImmutableUsurperGeneratorSetup.class.getName());
341 }
342 this.setup = immutableUsurperGeneratorSetup;
343 }
344
345
346
347
348
349
350 public ImmutableUsurperGeneratorSetup getSetup() {
351 return this.setup;
352 }
353
354
355
356
357
358
359
360
361
362
363 public void onMissingHandlers(OnMissingHandlers onMissingHandlers) {
364 UsurperGeneratorSetup mutableSetup = new UsurperGeneratorSetup(this.setup);
365 mutableSetup.onMissingHandlers(onMissingHandlers);
366 this.setup = mutableSetup.getImmutable();
367 }
368
369
370
371
372
373
374
375
376
377
378
379 public void registerPropertyTypeHandler(AbstractPropertyTypeHandler typeHandler) {
380 UsurperGeneratorSetup mutableSetup = new UsurperGeneratorSetup(this.setup);
381 mutableSetup.registerPropertyTypeHandler(typeHandler);
382 this.setup = mutableSetup.getImmutable();
383 }
384
385
386
387
388
389
390
391
392
393
394
395 public void registerPropertyTypeHandlers(Set<AbstractPropertyTypeHandler> typeHandlers) {
396 UsurperGeneratorSetup mutableSetup = new UsurperGeneratorSetup(this.setup);
397 mutableSetup.registerPropertyTypeHandlers(typeHandlers);
398 this.setup = mutableSetup.getImmutable();
399 }
400
401
402
403
404
405
406
407
408
409
410 public boolean hasPropertyTypeHandler(Class<?> type) {
411 return this.setup.hasPropertyTypeHandler(new PropertyTypeDefinition(type));
412 }
413
414
415
416
417
418
419
420
421
422
423 public AbstractPropertyTypeHandler getPropertyTypeHandler(Class<?> handledType) {
424 return this.setup.getPropertyTypeHandler(new PropertyTypeDefinition(handledType));
425 }
426
427
428
429
430
431
432
433
434
435
436
437 public void registerSpecificPropertyHandler(AbstractSpecificPropertyHandler propertyHandler) {
438 UsurperGeneratorSetup mutableSetup = new UsurperGeneratorSetup(this.setup);
439 mutableSetup.getSpecificPropertyHandlersMap().put(propertyHandler.getTargetProperty(), propertyHandler);
440 this.setup = mutableSetup.getImmutable();
441 }
442
443
444
445
446
447
448
449
450
451
452 public boolean hasSpecificPropertyHandler(Class<?> usurpatedClass, String handledProperty) {
453 return this.setup.getSpecificPropertyHandlersMap().containsKey(usurpatedClass.getName() + "." + handledProperty);
454 }
455
456
457
458
459
460
461
462
463
464
465 public AbstractSpecificPropertyHandler getSpecificPropertyHandler(Class<?> usurpatedClass, String handledProperty) {
466 return this.setup.getSpecificPropertyHandlersMap().get(usurpatedClass.getName() + "." + handledProperty);
467 }
468
469
470
471
472
473
474
475
476 public Map<ITargetDefinition, IHandler> getAllHandlers() {
477 return this.setup.getAllHandlers();
478 }
479
480
481
482
483
484
485
486
487
488
489
490
491
492 public void setAllHandlers(Map<ITargetDefinition, IHandler> handlers) {
493 UsurperGeneratorSetup mutableSetup = new UsurperGeneratorSetup(this.setup);
494 mutableSetup.setAllHandlers(handlers);
495 this.setup = mutableSetup.getImmutable();
496 }
497
498
499
500
501
502
503 public void usePropertyWritingMechanism(PropertyWritingMechanism propertyWritingMechanism) {
504 UsurperGeneratorSetup mutableSetup = new UsurperGeneratorSetup(this.setup);
505 mutableSetup.usePropertyWritingMechanism(propertyWritingMechanism);
506 this.setup = mutableSetup.getImmutable();
507 }
508
509
510
511
512 public void useConstructor(Class<?>... constructorParameterTypes) {
513 this.constructorParameterTypes = constructorParameterTypes;
514 }
515
516 }