package org.tynamo.services;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.util.StrategyRegistry;
import org.tynamo.descriptor.CollectionDescriptor;
import org.tynamo.descriptor.EmbeddedDescriptor;
import org.tynamo.descriptor.TynamoClassDescriptor;
import org.tynamo.descriptor.TynamoPropertyDescriptor;
import org.tynamo.descriptor.factories.DescriptorFactory;
import org.tynamo.exception.TynamoRuntimeException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* This class builds and caches TynamoClassDescriptors.
* Descriptors are build during application startup.
*/
public class DescriptorServiceImpl implements DescriptorService
{
private final StrategyRegistry<TynamoClassDescriptor> descriptorsRegistry;
private final List<TynamoClassDescriptor> descriptors;
/**
* For each class in types, a descriptor is built by the DescriptorFactory. Next it is decorated
* by each DescriptorDecorator in turn. Finally it is cached.
*
* @param types In the Tynamo default configuration this will be set to all classes in the Hibernate config
* @param descriptorFactory In default Tynamo this will be a ReflectionDescriptorFactory
* @see org.tynamo.descriptor.factories.DescriptorFactory
* @see org.tynamo.descriptor.decorators.DescriptorDecorator
*/
public DescriptorServiceImpl(final Collection<Class> types, DescriptorFactory descriptorFactory)
{
final Map<Class, TynamoClassDescriptor> descriptorsMap = new HashMap<Class, TynamoClassDescriptor>();
for (Class type : types)
{
try
{
TynamoClassDescriptor classDescriptor = descriptorFactory.buildClassDescriptor(type);
descriptorsMap.put(type, classDescriptor);
} catch (TynamoRuntimeException e)
{
// smile, do nothing, move on.
}
}
// second pass to find children
for (Class type : types)
{
findChildren(type, descriptorsMap);
}
this.descriptors = CollectionFactory.newList(descriptorsMap.values());
this.descriptorsRegistry = StrategyRegistry.newInstance(TynamoClassDescriptor.class, descriptorsMap, true);
}
public List<TynamoClassDescriptor> getAllDescriptors()
{
return descriptors;
}
public TynamoClassDescriptor getClassDescriptor(Class type)
{
return descriptorsRegistry.get(type);
}
private static void findChildren(Class type, Map<Class, TynamoClassDescriptor> descriptorsMap)
{
TynamoClassDescriptor classDescriptor = descriptorsMap.get(type);
for (TynamoPropertyDescriptor propertyDescriptor : classDescriptor.getPropertyDescriptors())
{
if (propertyDescriptor.isCollection())
{
if (((CollectionDescriptor) propertyDescriptor).isChildRelationship())
{
TynamoClassDescriptor collectionClassDescriptor = descriptorsMap.get(((CollectionDescriptor) propertyDescriptor).getElementType());
collectionClassDescriptor.setChild(true);
}
if (((CollectionDescriptor) propertyDescriptor).getInverseProperty() != null)
{
classDescriptor.setHasCyclicRelationships(true);
}
}
if (propertyDescriptor.isEmbedded() && !descriptorsMap.containsKey(propertyDescriptor.getPropertyType()))
{
TynamoClassDescriptor tynamoClassDescriptor = ((EmbeddedDescriptor) propertyDescriptor).getEmbeddedClassDescriptor();
descriptorsMap.put(tynamoClassDescriptor.getBeanType(), tynamoClassDescriptor);
}
}
}
}