001    package org.tynamo.descriptor.annotation;
002    
003    import ognl.Ognl;
004    import org.tynamo.descriptor.*;
005    
006    import java.beans.Introspector;
007    import java.beans.PropertyDescriptor;
008    import java.lang.annotation.Annotation;
009    import java.lang.reflect.Field;
010    import java.lang.reflect.Method;
011    import java.util.Map;
012    
013    /**
014     * Creates {@link InitialValueDescriptorExtension} and {@link PossibleValuesDescriptorExtension} extensions
015     * using the information retrieved from {@link InitialValue} and {@link PossibleValues} annotations.
016     */
017    public class OgnlAnnotationsDecorator implements DescriptorDecorator
018    {
019    
020            /**
021             * It holds the Map of variables to put into the available namespace (scope) for OGNL expressions.
022             */
023            private Map context;
024    
025            /**
026             * {@inheritDoc}
027             */
028            public TynamoClassDescriptor decorate(TynamoClassDescriptor descriptor)
029            {
030                    decoratePropertyDescriptors(descriptor);
031                    return descriptor;
032            }
033    
034            private void decoratePropertyDescriptors(TynamoClassDescriptor descriptor)
035            {
036                    for (TynamoPropertyDescriptor propertyDescriptor : descriptor.getPropertyDescriptors())
037                    {
038                            decoratePropertyDescriptor(propertyDescriptor);
039                            // recursively decorate components
040                            if (propertyDescriptor.isEmbedded())
041                            {
042                                    decorate((EmbeddedDescriptor) propertyDescriptor);
043                            }
044                    }
045            }
046    
047            private void decoratePropertyDescriptor(TynamoPropertyDescriptor propertyDescriptor)
048            {
049                    try
050                    {
051                            Field propertyField = propertyDescriptor.getBeanType().getDeclaredField(propertyDescriptor.getName());
052                            decorateFromAnnotations(propertyDescriptor, propertyField.getAnnotations());
053    
054                    } catch (Exception ex)
055                    {
056                            // don't care
057                    }
058                    try
059                    {
060                            PropertyDescriptor beanPropDescriptor = (PropertyDescriptor) Ognl.getValue("propertyDescriptors.{? name == '" + propertyDescriptor.getName() + "'}[0]",
061                                            Introspector.getBeanInfo(propertyDescriptor.getBeanType()));
062    
063                            Method readMethod = beanPropDescriptor.getReadMethod();
064                            decorateFromAnnotations(propertyDescriptor, readMethod.getAnnotations());
065                    }
066                    catch (Exception ex)
067                    {
068                            // don't care
069                    }
070            }
071    
072            private void decorateFromAnnotations(Descriptor descriptor, Annotation[] annotations)
073            {
074                    for (Annotation annotation : annotations)
075                    {
076                            if (annotation instanceof InitialValue)
077                            {
078                                    InitialValueDescriptorExtension extension = new InitialValueDescriptorExtension(((InitialValue) annotation).value(), context);
079                                    descriptor.addExtension(InitialValueDescriptorExtension.class.getName(), extension);
080                            } else if (annotation instanceof PossibleValues)
081                            {
082                                    PossibleValuesDescriptorExtension extension = new PossibleValuesDescriptorExtension(((PossibleValues) annotation).value(), context);
083                                    descriptor.addExtension(PossibleValuesDescriptorExtension.class.getName(), extension);
084                            }
085                    }
086            }
087    
088            /**
089             * sets the context value
090             *
091             * @param context
092             */
093            public void setContext(Map context)
094            {
095                    this.context = context;
096            }
097    }