1 package com.silvermindsoftware.hitch.meta;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import com.silvermindsoftware.hitch.ReadOnly;
20 import com.silvermindsoftware.hitch.config.BoundComponentConfig;
21 import com.silvermindsoftware.hitch.reflect.ClassManager;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 import java.lang.reflect.Field;
26 import java.lang.reflect.Method;
27 import java.util.*;
28
29
30
31
32
33
34
35 public class FormMeta {
36
37 private static final Logger log = LoggerFactory.getLogger(FormMeta.class);
38
39 private boolean annotationMetaCollected;
40
41 private Class componentClass;
42 private Map<String, ModelMeta> modelMap;
43 private List<ComponentMeta> componentMetaLists;
44
45 public FormMeta(Class componentClass) {
46 this(componentClass, new HashMap<String, ModelMeta>(), new ArrayList<ComponentMeta>());
47 }
48
49 public FormMeta(Class componentClass, Map modelMap, List componentMetaLists) {
50
51 this.annotationMetaCollected = false;
52 this.componentClass = componentClass;
53 this.modelMap = modelMap;
54 this.componentMetaLists = componentMetaLists;
55
56 }
57
58 public void putModelMeta(String id, String modelField) {
59
60 try {
61 putModelMeta(id, ClassManager.getClassInfo(componentClass).getField(modelField));
62 } catch (NoSuchFieldException e) {
63 throw new IllegalStateException(
64 "Field with name " + modelField +
65 " was not found in class" + componentClass.getName());
66 }
67
68 }
69
70 public void putModelMeta(String id, Field modelField) {
71 if (modelMap.containsKey(id)) {
72 log.info(
73 "Model of type "
74 + (modelMap.get(id)).getModelField().getType().getName()
75 + " with id of '" + id + "' already exists for class "
76 + componentClass.getName());
77 } else {
78 modelMap.put(id, new ModelMeta(modelField));
79 }
80
81 }
82
83 public ModelMeta getModelMeta(String modelId) {
84
85 if (!modelMap.containsKey(modelId))
86 throw new IllegalStateException(
87 "Model identified by " + modelId
88 + " does not exist for class " + componentClass.getName());
89
90 return modelMap.get(modelId);
91 }
92
93 public void addComponentMeta(String modelId, BoundComponentConfig boundComponentConfig, boolean autoBound) {
94
95 Field field;
96
97 try {
98 field = ClassManager.getClassInfo(componentClass).getField(boundComponentConfig.getComponentFieldName());
99 field.setAccessible(true);
100 } catch (NoSuchFieldException e) {
101 throw new IllegalStateException(
102 boundComponentConfig.getComponentFieldName() + " field was not found on class " + componentClass.getName());
103 }
104
105 addComponentMeta(
106 modelId, boundComponentConfig.getModelPropertyName(),
107 field, boundComponentConfig.getHandlerClass(),
108 boundComponentConfig.getHandlerParameters(), autoBound,
109 boundComponentConfig.getReadOnly(), boundComponentConfig.getType());
110 }
111
112 public void addComponentMeta(
113 String modelId, String modelProperty,
114 Field componentField, Class componentHandler,
115 String[] handlerParameters, boolean autoBound,
116 ReadOnly readOnly, Class type) {
117
118 if (!modelMap.containsKey(modelId))
119 throw new IllegalArgumentException("No model object found for id " + modelId);
120
121 ModelMeta modelMeta =
122 modelMap.get(modelId);
123
124 Class modelType = modelMeta.getModelField().getType();
125
126 ComponentMeta tempComponentMeta = new ComponentMeta(modelProperty, modelId);
127
128 if (componentMetaLists.contains(tempComponentMeta)) {
129
130 ComponentMeta componentMeta =
131 componentMetaLists.get(
132 componentMetaLists.indexOf(
133 tempComponentMeta));
134
135 if (componentMeta.isAutoBound() && autoBound == false) {
136 componentMetaLists.add(
137 componentMetaLists.indexOf(tempComponentMeta),
138 createComponentMeta(
139 modelType, modelProperty, modelId, componentField,
140 componentHandler, handlerParameters, autoBound, readOnly, type));
141 } else {
142 log.info(
143 "ComponentMeta already exists for property "
144 + modelProperty + " of model id" + modelId
145 + " for class " + modelType.getName());
146 }
147
148 } else {
149 componentMetaLists.add(
150 createComponentMeta(
151 modelType, modelProperty, modelId, componentField,
152 componentHandler, handlerParameters, autoBound, readOnly, type));
153 }
154 }
155
156 private ComponentMeta createComponentMeta(Class modelType, String modelProperty, String modelId, Field componentField, Class componentHandler, String[] handlerParameters, boolean autoBound, ReadOnly readOnly, Class type) {
157
158 Class propertyType = null;
159
160 Method modelPropertyGetterMethod = null;
161 boolean modelPropertyGetterMethodFound = false;
162
163 Method modelPropertySetterMethod = null;
164
165 Field modelPropertyField = null;
166
167 String mdlProp = modelProperty;
168
169
170 if (mdlProp.startsWith("m_")) {
171 mdlProp = mdlProp.substring(2);
172 }
173
174
175 try {
176 if (Map.class.isAssignableFrom(modelType)) {
177 modelPropertyGetterMethod =
178 ClassManager.getClassInfo(modelType).getMethod(
179 "get", new Class[]{Object.class});
180
181 if (modelPropertyGetterMethod != null) {
182 propertyType = modelPropertyGetterMethod.getReturnType();
183 modelPropertyGetterMethodFound = true;
184 }
185 } else {
186 modelPropertyGetterMethod =
187 ClassManager.getClassInfo(modelType).getGetterMethod(
188 composeGetterName(mdlProp));
189 modelPropertyGetterMethod.setAccessible(true);
190 if (modelPropertyGetterMethod != null) {
191 propertyType = modelPropertyGetterMethod.getReturnType();
192 modelPropertyGetterMethod.setAccessible(true);
193 modelPropertyGetterMethodFound = true;
194 }
195 }
196
197 } catch (NoSuchMethodException e) {
198 log.info(e.getMessage());
199 }
200
201
202 try {
203 modelPropertyField = ClassManager.getClassInfo(modelType).getField(mdlProp);
204 modelPropertyField.setAccessible(true);
205 if (propertyType == null) propertyType = modelPropertyField.getType();
206 } catch (NoSuchFieldException e) {
207 if (!modelPropertyGetterMethodFound)
208 throw new IllegalStateException(
209 "A getter method or a field was not found for property with name " + mdlProp);
210 }
211
212
213 try {
214 if (Map.class.isAssignableFrom(modelType)) {
215 modelPropertySetterMethod = ClassManager.getClassInfo(modelType).getSetterMethod("put", new Class[]{Object.class, Object.class});
216 } else {
217 modelPropertySetterMethod = ClassManager.getClassInfo(modelType).getSetterMethod(composeSetterName(modelProperty), new Class[]{propertyType});
218 modelPropertySetterMethod.setAccessible(true);
219 }
220 } catch (NoSuchMethodException e) {
221 log.info(e.getMessage());
222 }
223
224 ComponentMeta componentMeta =
225 new ComponentMeta(
226 modelType, modelProperty, modelId,
227 componentField, modelPropertyField,
228 modelPropertyGetterMethod, modelPropertySetterMethod,
229 componentHandler, handlerParameters,
230 autoBound, readOnly,
231 type == void.class ? propertyType : type
232 );
233 return componentMeta;
234 }
235
236 public Iterator<ComponentMeta> getComponentMetaIterator() {
237 return componentMetaLists.iterator();
238 }
239
240 public void setAnnotationMetaCollected(boolean annotationMetaCollected) {
241 this.annotationMetaCollected = annotationMetaCollected;
242 }
243
244 public boolean isAnnotationMetaCollected() {
245 return annotationMetaCollected;
246 }
247
248 public Class getComponentClass() {
249 return componentClass;
250 }
251
252 protected String composeSetterName(String propertyName) {
253 StringBuilder sb = new StringBuilder("set");
254 sb.append(propertyName.substring(0, 1).toUpperCase());
255 sb.append(propertyName.substring(1));
256 return sb.toString();
257 }
258
259 protected String composeGetterName(String propertyName) {
260 StringBuilder sb = new StringBuilder("get");
261 sb.append(propertyName.substring(0, 1).toUpperCase());
262 sb.append(propertyName.substring(1));
263 return sb.toString();
264 }
265
266
267 }