001 package org.trails.descriptor.annotation;
002
003 import java.beans.Introspector;
004 import java.beans.PropertyDescriptor;
005 import java.lang.annotation.Annotation;
006 import java.lang.reflect.Field;
007 import java.lang.reflect.Method;
008 import java.util.*;
009
010 import ognl.Ognl;
011 import org.trails.descriptor.*;
012
013 /**
014 * This class uses the annotations on a given class or property to modify its
015 * descriptor
016 *
017 * @author Chris Nelson
018 */
019 public class AnnotationDecorator implements DescriptorDecorator
020 {
021
022 public IClassDescriptor decorate(IClassDescriptor descriptor)
023 {
024
025 Annotation[] classAnnotations = descriptor.getType().getAnnotations();
026 IClassDescriptor decoratedDescriptor = (IClassDescriptor) decorateFromAnnotations(descriptor, classAnnotations);
027
028 decoratedDescriptor.setPropertyDescriptors(decoratePropertyDescriptors(descriptor));
029 sortDescriptors(decoratedDescriptor.getPropertyDescriptors());
030
031 decoratedDescriptor.setMethodDescriptors(decorateMethodDescriptors(descriptor));
032
033 return decoratedDescriptor;
034 }
035
036 private List<IPropertyDescriptor> decoratePropertyDescriptors(IClassDescriptor descriptor)
037 {
038 List<IPropertyDescriptor> decoratedPropertyDescriptors = new ArrayList<IPropertyDescriptor>();
039 for (IPropertyDescriptor propertyDescriptor : descriptor.getPropertyDescriptors())
040 {
041 IPropertyDescriptor clonedDescriptor = decoratePropertyDescriptor(propertyDescriptor);
042 // recursively decorate components
043 if (clonedDescriptor.isEmbedded())
044 {
045 clonedDescriptor = (EmbeddedDescriptor) decorate((EmbeddedDescriptor) clonedDescriptor);
046 }
047 decoratedPropertyDescriptors.add(clonedDescriptor);
048 }
049 return decoratedPropertyDescriptors;
050 }
051
052 private List<IMethodDescriptor> decorateMethodDescriptors(IClassDescriptor descriptor)
053 {
054 List<IMethodDescriptor> decoratedMethodDescriptors = new ArrayList<IMethodDescriptor>();
055 for (IMethodDescriptor methodDescriptor : descriptor.getMethodDescriptors())
056 {
057 IMethodDescriptor clonedDescriptor = decorateMethodDescriptor(methodDescriptor);
058 decoratedMethodDescriptors.add(clonedDescriptor);
059 }
060 return decoratedMethodDescriptors;
061 }
062
063 protected IPropertyDescriptor decoratePropertyDescriptor(IPropertyDescriptor propertyDescriptor)
064 {
065 IPropertyDescriptor clonedDescriptor = (IPropertyDescriptor) propertyDescriptor.clone();
066 try
067 {
068 Field propertyField = clonedDescriptor.getBeanType().getDeclaredField(propertyDescriptor.getName());
069 clonedDescriptor = (IPropertyDescriptor) decorateFromAnnotations(clonedDescriptor, propertyField.getAnnotations());
070
071 } catch (Exception ex)
072 {
073 // don't care
074 }
075 try
076 {
077 PropertyDescriptor beanPropDescriptor = (PropertyDescriptor) Ognl.getValue("propertyDescriptors.{? name == '" + propertyDescriptor.getName() + "'}[0]",
078 Introspector.getBeanInfo(clonedDescriptor.getBeanType()));
079
080 Method readMethod = beanPropDescriptor.getReadMethod();
081 clonedDescriptor = (IPropertyDescriptor) decorateFromAnnotations(clonedDescriptor, readMethod.getAnnotations());
082 }
083 catch (Exception ex)
084 {
085 //System.out.println(propertyDescriptor.getName());
086 //ex.printStackTrace();
087 // don't care
088 }
089 return clonedDescriptor;
090 }
091
092 protected IMethodDescriptor decorateMethodDescriptor(IMethodDescriptor methodDescriptor) {
093 try
094 {
095
096 return (IMethodDescriptor) decorateFromAnnotations(methodDescriptor, methodDescriptor.getMethod().getAnnotations());
097
098 } catch (NoSuchMethodException e)
099 {
100
101 }
102 return methodDescriptor;
103 }
104
105 /**
106 * Rearrange the property descriptors by their index
107 *
108 * @param propertyDescriptors
109 */
110 private void sortDescriptors(List<IPropertyDescriptor> propertyDescriptors)
111 {
112 for (IPropertyDescriptor propertyDescriptor : Collections.unmodifiableList(propertyDescriptors))
113 {
114 if (propertyDescriptor.getIndex() != IPropertyDescriptor.UNDEFINED_INDEX)
115 {
116 Collections.swap(propertyDescriptors, propertyDescriptor.getIndex(),
117 propertyDescriptors.indexOf(propertyDescriptor));
118 }
119 }
120 }
121
122 private IDescriptor decorateFromAnnotations(IDescriptor descriptor, Annotation[] annotations)
123 {
124 IDescriptor clonedDescriptor = (IDescriptor) descriptor.clone();
125 for (Annotation annotation : annotations)
126 {
127 // If the annotation type itself has a DescriptorAnnotation, it's one of ours
128 DescriptorAnnotation handlerAnnotation =
129 annotation.annotationType().getAnnotation(DescriptorAnnotation.class);
130 if (handlerAnnotation != null)
131 {
132 try
133 {
134 DescriptorAnnotationHandler handler = handlerAnnotation.value().newInstance();
135 clonedDescriptor = handler.decorateFromAnnotation(annotation, clonedDescriptor);
136 }
137 catch (Exception ex)
138 {
139 //ex.printStackTrace();
140 }
141 }
142 }
143 return clonedDescriptor;
144 }
145
146 }