001: package com.silvermindsoftware.hitch.meta;
002:
003: /**
004: * Copyright 2007 Brandon Goodin
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: import com.silvermindsoftware.hitch.ReadOnly;
020: import com.silvermindsoftware.hitch.config.BoundComponentConfig;
021: import com.silvermindsoftware.hitch.reflect.ClassManager;
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024:
025: import java.lang.reflect.Field;
026: import java.lang.reflect.Method;
027: import java.util.*;
028:
029: /**
030: * This class holds all of the meta data gathered from the different
031: * configuration mediums (annotations, BinderConfig).
032: */
033: public class FormMeta {
034:
035: private static final Log log = LogFactory.getLog(FormMeta.class);
036:
037: private boolean annotationMetaCollected;
038:
039: private Class componentClass;
040: private Map<String, ModelMeta> modelMap;
041: private List<ComponentMeta> componentMetaLists;
042:
043: public FormMeta(Class componentClass) {
044: this (componentClass, new HashMap<String, ModelMeta>(),
045: new ArrayList<ComponentMeta>());
046: }
047:
048: public FormMeta(Class componentClass, Map modelMap,
049: List componentMetaLists) {
050:
051: this .annotationMetaCollected = false;
052: this .componentClass = componentClass;
053: this .modelMap = modelMap;
054: this .componentMetaLists = componentMetaLists;
055:
056: }
057:
058: public void putModelMeta(String id, String modelField) {
059:
060: try {
061: putModelMeta(id, ClassManager.getClassInfo(componentClass)
062: .getField(modelField));
063: } catch (NoSuchFieldException e) {
064: throw new IllegalStateException("Field with name "
065: + modelField + " was not found in class"
066: + componentClass.getName());
067: }
068:
069: }
070:
071: public void putModelMeta(String id, Field modelField) {
072: if (modelMap.containsKey(id)) {
073: log.info("Model of type "
074: + (modelMap.get(id)).getModelField().getType()
075: .getName() + " with id of '" + id
076: + "' already exists for class "
077: + componentClass.getName());
078: } else {
079: modelMap.put(id, new ModelMeta(modelField));
080: }
081:
082: }
083:
084: public ModelMeta getModelMeta(String modelId) {
085:
086: if (!modelMap.containsKey(modelId))
087: throw new IllegalStateException("Model identified by "
088: + modelId + " does not exist for class "
089: + componentClass.getName());
090:
091: return modelMap.get(modelId);
092: }
093:
094: public void addComponentMeta(String modelId,
095: BoundComponentConfig boundComponentConfig, boolean autoBound) {
096:
097: Field field;
098:
099: try {
100: field = ClassManager.getClassInfo(componentClass).getField(
101: boundComponentConfig.getComponentFieldName());
102: field.setAccessible(true);
103: } catch (NoSuchFieldException e) {
104: throw new IllegalStateException(boundComponentConfig
105: .getComponentFieldName()
106: + " field was not found on class "
107: + componentClass.getName());
108: }
109:
110: addComponentMeta(modelId, boundComponentConfig
111: .getModelPropertyName(), field, boundComponentConfig
112: .getHandlerClass(), boundComponentConfig
113: .getHandlerParameters(), autoBound,
114: boundComponentConfig.getReadOnly(),
115: boundComponentConfig.getType());
116: }
117:
118: public void addComponentMeta(String modelId, String modelProperty,
119: Field componentField, Class componentHandler,
120: String[] handlerParameters, boolean autoBound,
121: ReadOnly readOnly, Class type) {
122:
123: if (!modelMap.containsKey(modelId))
124: throw new IllegalArgumentException(
125: "No model object found for id " + modelId);
126:
127: ModelMeta modelMeta = modelMap.get(modelId);
128:
129: Class modelType = modelMeta.getModelField().getType();
130:
131: ComponentMeta tempComponentMeta = new ComponentMeta(
132: modelProperty, modelId);
133:
134: if (componentMetaLists.contains(tempComponentMeta)) {
135:
136: ComponentMeta componentMeta = componentMetaLists
137: .get(componentMetaLists.indexOf(tempComponentMeta));
138:
139: if (componentMeta.isAutoBound() && autoBound == false) {
140: componentMetaLists.add(componentMetaLists
141: .indexOf(tempComponentMeta),
142: createComponentMeta(modelType, modelProperty,
143: modelId, componentField,
144: componentHandler, handlerParameters,
145: autoBound, readOnly, type));
146: } else {
147: log.info("ComponentMeta already exists for property "
148: + modelProperty + " of model id" + modelId
149: + " for class " + modelType.getName());
150: }
151:
152: } else {
153: componentMetaLists.add(createComponentMeta(modelType,
154: modelProperty, modelId, componentField,
155: componentHandler, handlerParameters, autoBound,
156: readOnly, type));
157: }
158: }
159:
160: private ComponentMeta createComponentMeta(Class modelType,
161: String modelProperty, String modelId, Field componentField,
162: Class componentHandler, String[] handlerParameters,
163: boolean autoBound, ReadOnly readOnly, Class type) {
164: // attain getter/setter/field for model property
165: Class propertyType = null;
166:
167: Method modelPropertyGetterMethod = null;
168: boolean modelPropertyGetterMethodFound = false;
169:
170: Method modelPropertySetterMethod = null;
171:
172: Field modelPropertyField = null;
173:
174: // getter
175: try {
176: if (Map.class.isAssignableFrom(modelType)) {
177: modelPropertyGetterMethod = ClassManager.getClassInfo(
178: modelType).getMethod("get",
179: new Class[] { Object.class });
180:
181: if (modelPropertyGetterMethod != null) {
182: propertyType = modelPropertyGetterMethod
183: .getReturnType();
184: modelPropertyGetterMethodFound = true;
185: }
186: } else {
187: modelPropertyGetterMethod = ClassManager.getClassInfo(
188: modelType).getGetterMethod(
189: composeGetterName(modelProperty));
190: modelPropertyGetterMethod.setAccessible(true);
191: if (modelPropertyGetterMethod != null) {
192: propertyType = modelPropertyGetterMethod
193: .getReturnType();
194: modelPropertyGetterMethod.setAccessible(true);
195: modelPropertyGetterMethodFound = true;
196: }
197: }
198:
199: } catch (NoSuchMethodException e) {
200: log.info(e.getMessage());
201: }
202:
203: // field
204: try {
205: modelPropertyField = ClassManager.getClassInfo(modelType)
206: .getField(modelProperty);
207: modelPropertyField.setAccessible(true);
208: if (propertyType == null)
209: propertyType = modelPropertyField.getType();
210: } catch (NoSuchFieldException e) {
211: if (!modelPropertyGetterMethodFound)
212: throw new IllegalStateException(
213: "A getter method or a field was not found for property with name "
214: + modelProperty);
215: }
216:
217: // setter
218: try {
219: if (Map.class.isAssignableFrom(modelType)) {
220: modelPropertySetterMethod = ClassManager.getClassInfo(
221: modelType).getSetterMethod("put",
222: new Class[] { Object.class, Object.class });
223: } else {
224: modelPropertySetterMethod = ClassManager.getClassInfo(
225: modelType).getSetterMethod(
226: composeSetterName(modelProperty),
227: new Class[] { propertyType });
228: modelPropertySetterMethod.setAccessible(true);
229: }
230: } catch (NoSuchMethodException e) {
231: log.info(e.getMessage());
232: }
233:
234: ComponentMeta componentMeta = new ComponentMeta(modelType,
235: modelProperty, modelId, componentField,
236: modelPropertyField, modelPropertyGetterMethod,
237: modelPropertySetterMethod, componentHandler,
238: handlerParameters, autoBound, readOnly,
239: type == void.class ? propertyType : type);
240: return componentMeta;
241: }
242:
243: public Iterator<ComponentMeta> getComponentMetaIterator() {
244: return componentMetaLists.iterator();
245: }
246:
247: public void setAnnotationMetaCollected(
248: boolean annotationMetaCollected) {
249: this .annotationMetaCollected = annotationMetaCollected;
250: }
251:
252: public boolean isAnnotationMetaCollected() {
253: return annotationMetaCollected;
254: }
255:
256: public Class getComponentClass() {
257: return componentClass;
258: }
259:
260: protected String composeSetterName(String propertyName) {
261: StringBuilder sb = new StringBuilder("set");
262: sb.append(propertyName.substring(0, 1).toUpperCase());
263: sb.append(propertyName.substring(1));
264: return sb.toString();
265: }
266:
267: protected String composeGetterName(String propertyName) {
268: StringBuilder sb = new StringBuilder("get");
269: sb.append(propertyName.substring(0, 1).toUpperCase());
270: sb.append(propertyName.substring(1));
271: return sb.toString();
272: }
273:
274: }
|