001    package org.tynamo.descriptor;
002    
003    import org.apache.commons.beanutils.BeanUtils;
004    import org.apache.commons.logging.Log;
005    import org.apache.commons.logging.LogFactory;
006    import org.tynamo.util.Utils;
007    
008    import java.beans.BeanDescriptor;
009    import java.beans.BeanInfo;
010    import java.beans.Introspector;
011    import java.lang.reflect.InvocationTargetException;
012    import java.util.List;
013    
014    /**
015     * Generate descriptors using reflection on the underlying class.
016     * ReflectionDescriptorFactory.buildClassDescriptor() is the only public method
017     * here.
018     */
019    public class ReflectionDescriptorFactory implements DescriptorFactory
020    {
021    
022            protected static final Log LOG = LogFactory.getLog(ReflectionDescriptorFactory.class);
023    
024            private final MethodDescriptorFactory methodDescriptorFactory;
025            private final PropertyDescriptorFactory propertyDescriptorFactory;
026            private final List<DescriptorDecorator> decorators;
027    
028            /**
029             * @param decorators                            In the default Tynamo configuration this will contain a HibernateDescriptorDecorator and an AnnotationDecorator
030             * @param methodDescriptorFactory
031             * @param propertyDescriptorFactory
032             */
033            public ReflectionDescriptorFactory(final List<DescriptorDecorator> decorators, MethodDescriptorFactory methodDescriptorFactory, PropertyDescriptorFactory propertyDescriptorFactory)
034            {
035                    this.decorators = decorators;
036                    this.methodDescriptorFactory = methodDescriptorFactory;
037                    this.propertyDescriptorFactory = propertyDescriptorFactory;
038            }
039    
040            /**
041             * Given a type, build a class descriptor
042             *
043             * @param type The type to build for
044             * @return a completed class descriptor
045             */
046            public TynamoClassDescriptor buildClassDescriptor(Class type)
047            {
048                    try
049                    {
050                            TynamoClassDescriptor descriptor = new TynamoClassDescriptorImpl(type);
051                            BeanInfo beanInfo = Introspector.getBeanInfo(type);
052    
053                            BeanUtils.copyProperties(descriptor, beanInfo.getBeanDescriptor());
054                            descriptor.setPropertyDescriptors(propertyDescriptorFactory.buildPropertyDescriptors(type, beanInfo));
055                            descriptor.setMethodDescriptors(methodDescriptorFactory.buildMethodDescriptors(type, beanInfo));
056    
057                            descriptor = applyDecorators(descriptor);
058    
059                            return descriptor;
060    
061                    } catch (IllegalAccessException e)
062                    {
063                            LOG.error(e.getMessage());
064                            e.printStackTrace();
065                    } catch (InvocationTargetException e)
066                    {
067                            LOG.error(e.getMessage());
068                            e.printStackTrace();
069                    } catch (Exception e)
070                    {
071                            LOG.error(e.toString());
072                            e.printStackTrace();
073                    }
074                    return null;
075            }
076    
077            /**
078             * Have the decorators decorate this descriptor
079             *
080             * @param descriptor
081             * @param decorators
082             * @return The resulting descriptor after all decorators are applied
083             */
084            private TynamoClassDescriptor applyDecorators(TynamoClassDescriptor descriptor)
085            {
086                    for (DescriptorDecorator decorator : decorators)
087                    {
088                            descriptor = decorator.decorate(descriptor);
089                    }
090                    return descriptor;
091            }
092    }