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