1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.javagen.agile.core.visitor;
17
18 import java.beans.BeanInfo;
19 import java.beans.Introspector;
20 import java.beans.PropertyDescriptor;
21 import java.beans.PropertyEditor;
22 import java.beans.PropertyEditorManager;
23 import java.lang.reflect.Constructor;
24 import java.lang.reflect.Method;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.javagen.agile.core.annotation.DefaultValue;
31 import org.javagen.agile.core.model.Model;
32
33 /***
34 * Walk a model tree and set all non-null values to <code>DefaultValue</code> if present.
35 * Requires property types to have a String constructor or PropertyEditor defined.
36 *
37 * @see org.javagen.agile.core.annotation.DefaultValue
38 * @see PropertyEditorManager
39 * @author Richard Easterling
40 */
41 public class DefaultValueVisitor extends DefaultVisitor {
42
43 Map<Class<?>, List<DefaultSetter>> cachedSetters = new HashMap<Class<?>, List<DefaultSetter>>();
44
45
46
47
48
49 public void visit(Model model) {
50 List<DefaultSetter> setters = cachedSetters.get(model.getClass());
51 if (setters==null) {
52 setters = load(model);
53 cachedSetters.put(model.getClass(), setters);
54 }
55 for(DefaultSetter setter : setters) {
56 setter.set(model);
57 }
58
59 }
60
61
62
63
64
65 private List<DefaultSetter> load(Model model) {
66 List<DefaultSetter> setters = new ArrayList<DefaultSetter>();
67 try {
68 BeanInfo beanInfo = Introspector.getBeanInfo(model.getClass());
69 for(PropertyDescriptor propDesc : beanInfo.getPropertyDescriptors()) {
70 Class<?> type = propDesc.getPropertyType();
71 Method getMethod = propDesc.getReadMethod();
72 DefaultValue defaultValue = getMethod==null ? null : getMethod.getAnnotation(DefaultValue.class);
73
74 if (defaultValue==null)
75 continue;
76 Object value = defaultValue.value();
77 if ( ! type.getClass().equals(String.class) ) {
78 PropertyEditor propEditor = PropertyEditorManager.findEditor(type);
79 if (propEditor!=null) {
80 propEditor.setAsText(value.toString());
81 value = propEditor.getValue();
82 } else {
83 Constructor<?> constructor = type.getConstructor(new Class[]{String.class});
84 if (constructor!=null) {
85 value = constructor.newInstance(new Object[]{value});
86 } else {
87 throw new RuntimeException("can't set @DefaultValue("+value+") on "+model.getClass().getName()+"."+propDesc.getName()+" no PropertyEditor registered or String constructor found.");
88 }
89 }
90 }
91 Method setMethod = propDesc.getWriteMethod();
92 if (setMethod==null)
93 throw new RuntimeException("can't set @DefaultValue("+value+") on "+model.getClass().getName()+"."+propDesc.getName()+" no PropertyEditor registered or setter method found.");
94 setters.add( new DefaultSetter(value, setMethod, getMethod));
95 }
96
97 return setters;
98 } catch (Exception e) {
99 throw new RuntimeException(e);
100 }
101 }
102
103
104
105
106
107 static class DefaultSetter {
108 private Object[] defaultValueArg;
109 private Method setMethod;
110 private Method getMethod;
111 static final Object[] NO_ARGS = new Object[0];
112
113 public DefaultSetter(Object defaultValue, Method setMethod, Method getMethod) {
114 this.defaultValueArg = new Object[]{defaultValue};
115 this.setMethod = setMethod;
116 this.getMethod = getMethod;
117 }
118
119 public void set(Model model) {
120 try {
121 if (getMethod.invoke(model, NO_ARGS)==null)
122 setMethod.invoke(model, defaultValueArg);
123 } catch (Exception e) {
124 throw new RuntimeException(e);
125 }
126 }
127 }
128
129
130 }