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