001    package org.tynamo.services;
002    
003    import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
004    import org.apache.tapestry5.ioc.internal.util.Defense;
005    import org.apache.tapestry5.ioc.util.StrategyRegistry;
006    import org.tynamo.descriptor.*;
007    
008    import java.util.Collection;
009    import java.util.HashMap;
010    import java.util.List;
011    import java.util.Map;
012    
013    /**
014     * This class builds and caches TynamoClassDescriptors.
015     * Descriptors are build during application startup.
016     */
017    public class DescriptorServiceImpl implements DescriptorService
018    {
019            private final StrategyRegistry<TynamoClassDescriptor> descriptorsRegistry;
020            private final List<TynamoClassDescriptor> descriptors;
021    
022            /**
023             * For each class in types, a descriptor is built by the DescriptorFactory.  Next it is decorated
024             * by each DescriptorDecorator in turn.  Finally it is cached.
025             *
026             * @param types                  In the Tynamo default configuration this will be set to all classes in the Hibernate config
027             * @param descriptorFactory In default Tynamo this will be a ReflectionDescriptorFactory
028             * @see DescriptorFactory
029             * @see DescriptorDecorator
030             */
031            public DescriptorServiceImpl(final Collection<Class> types, DescriptorFactory descriptorFactory)
032            {
033                    Map<Class, TynamoClassDescriptor> descriptorsMap = new HashMap<Class, TynamoClassDescriptor>();
034                    for (Class type : types)
035                    {
036                            descriptorsMap.put(type, descriptorFactory.buildClassDescriptor(type));
037                    }
038    
039                    this.descriptors = CollectionFactory.newList(descriptorsMap.values());
040                    this.descriptorsRegistry = StrategyRegistry.newInstance(TynamoClassDescriptor.class, descriptorsMap, true);
041    
042                    // second pass to find children
043                    for (TynamoClassDescriptor classDescriptor : descriptorsMap.values())
044                    {
045                            findChildren(classDescriptor);
046                    }
047    
048            }
049    
050            public List<TynamoClassDescriptor> getAllDescriptors()
051            {
052                    return descriptors;
053            }
054    
055            public TynamoClassDescriptor getClassDescriptor(Class type)
056            {
057                    Defense.notNull(type, "type");
058                    return descriptorsRegistry.get(type);
059            }
060    
061            private void findChildren(TynamoClassDescriptor classDescriptor)
062            {
063                    for (TynamoPropertyDescriptor propertyDescriptor : classDescriptor.getPropertyDescriptors())
064                    {
065                            if (propertyDescriptor.isCollection())
066                            {
067                                    if (((CollectionDescriptor) propertyDescriptor).isChildRelationship())
068                                    {
069                                            TynamoClassDescriptor collectionClassDescriptor = getClassDescriptor(((CollectionDescriptor) propertyDescriptor).getElementType());
070                                            collectionClassDescriptor.setChild(true);
071                                    }
072                                    if (((CollectionDescriptor) propertyDescriptor).getInverseProperty() != null)
073                                    {
074                                            classDescriptor.setHasCyclicRelationships(true);
075                                    }
076                            }
077                    }
078            }
079    
080    }