001 package org.trails.descriptor;
002
003 import java.util.ArrayList;
004 import java.util.Collections;
005 import java.util.Comparator;
006 import java.util.HashMap;
007 import java.util.List;
008 import java.util.Map;
009
010 import ognl.OgnlException;
011
012 /**
013 * This class builds and caches IClassDescriptors. Descriptors are build during the init
014 * method which is called by Spring during application startup
015 *
016 * @author cnelson
017 * @see IClassDescriptor
018 */
019 public class TrailsDescriptorService implements DescriptorService
020 {
021 protected List<Class> types;
022 protected Map<Class, IClassDescriptor> descriptors = new HashMap<Class, IClassDescriptor>();
023 private List<DescriptorDecorator> decorators = new ArrayList<DescriptorDecorator>();
024 private DescriptorFactory descriptorFactory;
025
026 /**
027 * For each class in types, a descriptor is built by the DescriptorFactory. Next it is decorated
028 * by each DescriptorDecorator in turn. Finally it is cached.
029 *
030 * @throws OgnlException
031 * @see DescriptorFactory
032 * @see DescriptorDecorator
033 */
034 public void init() throws OgnlException
035 {
036 descriptors.clear();
037 for (Class type : types)
038 {
039 IClassDescriptor descriptor = getDescriptorFactory().buildClassDescriptor(type);
040 descriptor = applyDecorators(descriptor);
041 descriptors.put(type, descriptor);
042 }
043 // second pass to find children and set up descriptor parents
044 for (IClassDescriptor iClassDescriptor : descriptors.values())
045 {
046 findChildren(iClassDescriptor);
047 }
048 }
049
050 public List<IClassDescriptor> getAllDescriptors()
051 {
052 List<IClassDescriptor> allDescriptors = new ArrayList<IClassDescriptor>(descriptors.values());
053 Collections.sort(allDescriptors, new Comparator<IClassDescriptor>()
054 {
055 public int compare(IClassDescriptor o1, IClassDescriptor o2)
056 {
057 return o1.getDisplayName().compareTo(o2.getDisplayName());
058 }
059 });
060 return allDescriptors;
061 }
062
063 /* (non-Javadoc)
064 * @see org.trails.descriptor.IDescriptorFactory#buildClassDescriptor(java.lang.Class)
065 */
066 public IClassDescriptor getClassDescriptor(Class type)
067 {
068 if (type.getName().contains("CGLIB"))
069 {
070 return descriptors.get(type.getSuperclass());
071 } else
072 {
073 return descriptors.get(type);
074 }
075 }
076
077 protected void findChildren(IClassDescriptor iClassDescriptor)
078 {
079 for (IPropertyDescriptor propertyDescriptor : iClassDescriptor.getPropertyDescriptors())
080 {
081 if (propertyDescriptor.isCollection())
082 {
083 if (((CollectionDescriptor) propertyDescriptor).isChildRelationship())
084 {
085 IClassDescriptor collectionClassDescriptor = getClassDescriptor(((CollectionDescriptor) propertyDescriptor).getElementType());
086 collectionClassDescriptor.setChild(true);
087 }
088 if (((CollectionDescriptor) propertyDescriptor).getInverseProperty() != null)
089 {
090 iClassDescriptor.setHasCyclicRelationships(true);
091 }
092 }
093 }
094 }
095
096 /**
097 * Have the decorators decorate this descriptor todo what are decorators for and/or why would I want to call this
098 * menthod?
099 *
100 * @param descriptor
101 * @return The resulting descriptor after all decorators are applied
102 */
103 protected IClassDescriptor applyDecorators(IClassDescriptor descriptor)
104 {
105 IClassDescriptor currDescriptor = descriptor;
106 for (DescriptorDecorator decorator : getDecorators())
107 {
108 currDescriptor = decorator.decorate(currDescriptor);
109 }
110 return currDescriptor;
111 }
112
113 /**
114 * In the Trails default configuration this will be set
115 * to all classes in the Hibernate config
116 *
117 * @return
118 */
119 public List getTypes()
120 {
121 return types;
122 }
123
124 /**
125 * @param types all the classes this service should describe
126 */
127 public void setTypes(List<Class> types)
128 {
129 this.types = types;
130 }
131
132 /**
133 * In the default Trails configuration this will contain a HibernateDescriptorDecorator
134 * and an AnnotationDecorator
135 *
136 * @return
137 * @see org.trails.hibernate.HibernateDescriptorDecorator
138 * @see org.trails.descriptor.annotation.AnnotationDecorator
139 */
140 public List<DescriptorDecorator> getDecorators()
141 {
142 return decorators;
143 }
144
145 public void setDecorators(List<DescriptorDecorator> decorators)
146 {
147 this.decorators = decorators;
148 }
149
150 /**
151 * In default Trails this will be a ReflectionDescriptorFactory
152 *
153 * @return
154 * @see ReflectionDescriptorFactory
155 */
156 public DescriptorFactory getDescriptorFactory()
157 {
158 return descriptorFactory;
159 }
160
161 public void setDescriptorFactory(DescriptorFactory descriptorFactory)
162 {
163 this.descriptorFactory = descriptorFactory;
164 }
165 }