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 }