001    package org.tynamo.services;
002    
003    import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
004    
005    import org.apache.tapestry5.ioc.util.StrategyRegistry;
006    import org.tynamo.descriptor.*;
007    import org.tynamo.descriptor.factories.DescriptorFactory;
008    
009    import java.util.Collection;
010    import java.util.HashMap;
011    import java.util.List;
012    import java.util.Map;
013    
014    /**
015     * This class builds and caches TynamoClassDescriptors.
016     * Descriptors are build during application startup.
017     */
018    public class DescriptorServiceImpl implements DescriptorService
019    {
020            private final StrategyRegistry<TynamoClassDescriptor> descriptorsRegistry;
021            private final List<TynamoClassDescriptor> descriptors;
022    
023            /**
024             * For each class in types, a descriptor is built by the DescriptorFactory.  Next it is decorated
025             * by each DescriptorDecorator in turn.  Finally it is cached.
026             *
027             * @param types                  In the Tynamo default configuration this will be set to all classes in the Hibernate config
028             * @param descriptorFactory In default Tynamo this will be a ReflectionDescriptorFactory
029             * @see org.tynamo.descriptor.factories.DescriptorFactory
030             * @see org.tynamo.descriptor.decorators.DescriptorDecorator
031             */
032            public DescriptorServiceImpl(final Collection<Class> types, DescriptorFactory descriptorFactory)
033            {
034                    Map<Class, TynamoClassDescriptor> descriptorsMap = new HashMap<Class, TynamoClassDescriptor>();
035                    for (Class type : types)
036                    {
037                            descriptorsMap.put(type, descriptorFactory.buildClassDescriptor(type));
038                    }
039    
040                    this.descriptors = CollectionFactory.newList(descriptorsMap.values());
041                    this.descriptorsRegistry = StrategyRegistry.newInstance(TynamoClassDescriptor.class, descriptorsMap, true);
042    
043                    // second pass to find children
044                    for (TynamoClassDescriptor classDescriptor : descriptorsMap.values())
045                    {
046                            findChildren(classDescriptor);
047                    }
048    
049            }
050    
051            public List<TynamoClassDescriptor> getAllDescriptors()
052            {
053                    return descriptors;
054            }
055    
056            public TynamoClassDescriptor getClassDescriptor(Class type)
057            {
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    }