001: package org.conform.modifier;
002:
003: import java.lang.reflect.Field;
004: import java.lang.reflect.Constructor;
005: import java.lang.annotation.Annotation;
006: import java.util.HashMap;
007:
008: import org.apache.commons.logging.Log;
009: import org.apache.commons.logging.LogFactory;
010:
011: import org.conform.format.*;
012: import org.conform.*;
013: import org.conform.validator.ValidatorImplementation;
014:
015: public class AnnotationModifier implements Modifier {
016: private BeanMetaProvider beanMetaProvider;
017: private Log logger = LogFactory.getLog(getClass());
018:
019: public AnnotationModifier() {
020: }
021:
022: public AnnotationModifier(BeanMetaProvider beanMetaProvider) {
023: this .beanMetaProvider = beanMetaProvider;
024: }
025:
026: public void setBeanMetaProvider(BeanMetaProvider beanMetaProvider) {
027: this .beanMetaProvider = beanMetaProvider;
028: }
029:
030: public void modify(BeanMeta beanMeta) throws ModifierException {
031: Class type = beanMeta.getType();
032: org.conform.Bean beanAnnotation = (org.conform.Bean) type
033: .getAnnotation(org.conform.Bean.class);
034: if (beanAnnotation != null) {
035: String pattern = beanAnnotation.pattern();
036: if (pattern != null)
037: beanMeta.setAttribute(PropertyMeta.ATTRIBUTE_PATTERN,
038: pattern);
039: String patternKey = beanAnnotation.patternKey();
040: if (patternKey != null)
041: beanMeta.setAttribute(
042: PropertyMeta.ATTRIBUTE_PATTERN_KEY, patternKey);
043: }
044:
045: FormatType formatType = beanAnnotation != null ? beanAnnotation
046: .format() : null;
047: String formatClassName = beanAnnotation != null ? beanAnnotation
048: .formatClass()
049: : null;
050: beanMeta.setFormat(configureFormat(beanMeta, formatType,
051: formatClassName));
052:
053: formatDeclaredFields(type, beanMeta);
054: }
055:
056: private void formatDeclaredFields(Class type, BeanMeta beanMeta) {
057: /*
058: Class.getFields() returns all accessible (public) fields (also fields from super classes, but only the public ones)
059: Class.getDeclaredFields() returns all (also non public ones) fields from the class (does not inspect the supper classes)
060: */
061: for (Field field : type.getDeclaredFields()) {
062: PropertyMeta propertyMeta = beanMeta.getProperty(field
063: .getName());
064: if (propertyMeta == null)
065: continue;
066:
067: // copy meta from referenced property
068: PropertyReference propertyReferenceAnnotation = field
069: .getAnnotation(PropertyReference.class);
070: if (propertyReferenceAnnotation != null) {
071: try {
072: Class inheritClazz = Class
073: .forName(propertyReferenceAnnotation
074: .className());
075: BeanMeta inheritBeanMeta = beanMetaProvider
076: .getBeanMeta(inheritClazz);
077: PropertyMeta inheritPropertyMeta = inheritBeanMeta
078: .getProperty(propertyReferenceAnnotation
079: .propertyName());
080: if (inheritPropertyMeta == null)
081: throw new IllegalArgumentException(
082: "Referenced property '"
083: + propertyReferenceAnnotation
084: .propertyName()
085: + "' not found in '"
086: + propertyReferenceAnnotation
087: .className() + "'");
088:
089: propertyMeta.setDomainProvider(inheritPropertyMeta
090: .getDomainProvider());
091: propertyMeta.setFormat(inheritPropertyMeta
092: .getFormat());
093: propertyMeta.setMandatory(inheritPropertyMeta
094: .isMandatory());
095: propertyMeta.setPriority(inheritPropertyMeta
096: .getPriority());
097: propertyMeta.setReadable(inheritPropertyMeta
098: .isReadable());
099: propertyMeta.setValidators(inheritPropertyMeta
100: .getValidators());
101: propertyMeta.setWritable(inheritPropertyMeta
102: .isWritable());
103: propertyMeta.setApplicable(inheritPropertyMeta
104: .isApplicable());
105: if (propertyMeta.getAttributes() == null) {
106: propertyMeta.setAttributes(new HashMap());
107: }
108: if (inheritPropertyMeta.getAttributes() == null) {
109: logger.warn("No attribute found for property: "
110: + inheritPropertyMeta.getName()
111: + " of class: "
112: + inheritBeanMeta.getName());
113: } else {
114: propertyMeta.getAttributes().putAll(
115: inheritPropertyMeta.getAttributes());
116: }
117: propertyMeta.setAttribute("inheritBean",
118: inheritBeanMeta.getType());
119: propertyMeta.setAttribute("inheritProperty",
120: inheritPropertyMeta.getName());
121: } catch (Exception e) {
122: e.printStackTrace();
123: }
124: }
125:
126: // modify own meta
127: org.conform.Property propertyAnnotation = field
128: .getAnnotation(org.conform.Property.class);
129: if (propertyAnnotation != null) {
130: String readable = propertyAnnotation.readable();
131: if (readable != null && readable.length() > 0)
132: propertyMeta.setReadable(Boolean.valueOf(readable));
133: String writable = propertyAnnotation.writable();
134: if (writable != null && writable.length() > 0)
135: propertyMeta.setWritable(Boolean.valueOf(writable));
136: String applicable = propertyAnnotation.applicable();
137: if (applicable != null && applicable.length() > 0)
138: propertyMeta.setApplicable(Boolean
139: .valueOf(applicable));
140: String mandatory = propertyAnnotation.mandatory();
141: if (mandatory != null && mandatory.length() > 0)
142: propertyMeta.setMandatory(Boolean
143: .valueOf(mandatory));
144: String pattern = propertyAnnotation.pattern();
145: if (pattern != null && pattern.length() > 0)
146: propertyMeta.setAttribute(
147: PropertyMeta.ATTRIBUTE_PATTERN, pattern);
148: String patternKey = propertyAnnotation.patternKey();
149: if (patternKey != null && patternKey.length() > 0)
150: propertyMeta.setAttribute(
151: PropertyMeta.ATTRIBUTE_PATTERN_KEY,
152: patternKey);
153: int scale = propertyAnnotation.scale();
154: if (scale != -1)
155: propertyMeta.setAttribute(
156: PropertyMeta.ATTRIBUTE_SCALE, scale);
157: int precision = propertyAnnotation.precision();
158: if (precision != -1)
159: propertyMeta
160: .setAttribute(
161: PropertyMeta.ATTRIBUTE_PRECISION,
162: precision);
163: int length = propertyAnnotation.length();
164: if (length != -1)
165: propertyMeta.setAttribute(
166: PropertyMeta.ATTRIBUTE_LENGTH, length);
167: int priority = propertyAnnotation.priority();
168: if (priority != -1)
169: propertyMeta.setPriority(priority);
170: }
171:
172: FormatType formatType = propertyAnnotation != null ? propertyAnnotation
173: .format()
174: : null;
175: String formatClassName = propertyAnnotation != null ? propertyAnnotation
176: .formatClass()
177: : null;
178: propertyMeta.setFormat(configureFormat(propertyMeta,
179: formatType, formatClassName));
180: configureValidators(propertyMeta, field);
181: }
182:
183: if (type.getSuperclass() != null
184: && !type.getSuperclass().getName().startsWith("java")) {
185: formatDeclaredFields(type.getSuperclass(), beanMeta);
186: }
187: }
188:
189: private void configureValidators(PropertyMeta propertyMeta,
190: Field field) {
191: for (Annotation annotation : field.getAnnotations()) {
192: try {
193: ValidatorImplementation implementation = annotation
194: .annotationType().getAnnotation(
195: ValidatorImplementation.class);
196: if (implementation != null) {
197: Class<? extends Validator> validatorClass = implementation
198: .CLASS();
199: Constructor<? extends Validator> constructor = validatorClass
200: .getConstructor(Annotation.class);
201: Validator validator = constructor
202: .newInstance(annotation);
203: propertyMeta.addValidator(validator);
204: }
205: } catch (Exception e) {
206: e.printStackTrace();
207: }
208: }
209: }
210:
211: private Format configureFormat(Meta meta, FormatType formatType,
212: String formatClassName) {
213: if (formatType == null)
214: formatType = FormatType.NONE;
215:
216: switch (formatType) {
217: case TEMPLATE:
218: return new TemplateFormat();
219: case COLLECTION_SIZE:
220: return new CollectionSizeFormat();
221: case CUSTOM:
222: if (formatClassName != null) {
223: try {
224: Class formatClass = getClassLoader().loadClass(
225: formatClassName);
226: return (Format) formatClass.newInstance();
227: } catch (Exception e) {
228: logger.warn(meta.getName(), e);
229: }
230: }
231: default:
232: if (meta instanceof PropertyMeta) {
233: meta.setAttribute("formatType", formatType);
234: return FormatFactory.getInstance().getFormat(
235: (PropertyMeta) meta);
236: } else
237: return null;
238: }
239: }
240:
241: public ClassLoader getClassLoader() {
242: return Thread.currentThread().getContextClassLoader();
243: }
244: }
|