package org.etk.orm.plugins.mapper; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.etk.orm.api.format.ObjectFormatter; import org.etk.orm.core.EmbeddedContext; import org.etk.orm.core.EntityContext; import org.etk.orm.core.ObjectContext; import org.etk.orm.plugins.bean.ValueKind; import org.etk.orm.plugins.bean.mapping.AttributeMapping; import org.etk.orm.plugins.bean.mapping.BeanMapping; import org.etk.orm.plugins.bean.mapping.CreateMapping; import org.etk.orm.plugins.bean.mapping.DestroyMapping; import org.etk.orm.plugins.bean.mapping.FindByIdMapping; import org.etk.orm.plugins.bean.mapping.MappingVisitor; import org.etk.orm.plugins.bean.mapping.NodeTypeKind; import org.etk.orm.plugins.bean.mapping.PropertiesMapping; import org.etk.orm.plugins.bean.mapping.RelationshipMapping; import org.etk.orm.plugins.bean.mapping.ValueMapping; import org.etk.orm.plugins.bean.type.SimpleTypeProvider; import org.etk.orm.plugins.bean.type.SimpleTypeResolver; import org.etk.orm.plugins.common.ObjectInstantiator; import org.etk.orm.plugins.mapper.nodeattribute.JCRNodeAttributePropertyMapper; import org.etk.orm.plugins.mapper.onetomany.hierarchical.AnyChildMultiValueMapper; import org.etk.orm.plugins.mapper.onetomany.hierarchical.JCRAnyChildCollectionPropertyMapper; import org.etk.orm.plugins.mapper.onetomany.hierarchical.JCRAnyChildParentPropertyMapper; import org.etk.orm.plugins.mapper.onetomany.reference.JCRNamedReferentPropertyMapper; import org.etk.orm.plugins.mapper.onetomany.reference.JCRReferentCollectionPropertyMapper; import org.etk.orm.plugins.mapper.onetoone.embedded.JCREmbeddedParentPropertyMapper; import org.etk.orm.plugins.mapper.onetoone.embedded.JCREmbeddedPropertyMapper; import org.etk.orm.plugins.mapper.property.JCRNamedChildParentPropertyMapper; import org.etk.orm.plugins.mapper.property.JCRNamedChildPropertyMapper; import org.etk.orm.plugins.mapper.property.JCRPropertyDetypedPropertyMapper; import org.etk.orm.plugins.mapper.property.JCRPropertyMultiValuedPropertyMapper; import org.etk.orm.plugins.mapper.property.JCRPropertySingleValuedPropertyMapper; import org.etk.orm.plugins.vt2.ValueTypeFactory; public class MapperBuilder { /** . */ private final SimpleTypeResolver simpleTypeResolver; /** . */ private final ValueTypeFactory valueTypeFactory; public MapperBuilder(SimpleTypeResolver simpleTypeResolver) { this.simpleTypeResolver = simpleTypeResolver; this.valueTypeFactory = new ValueTypeFactory(simpleTypeResolver); } public Collection<ObjectMapper<?>> build(Collection<BeanMapping> beanMappings) { Context ctx = new Context(); ctx.start(); for (BeanMapping beanMapping : beanMappings) { beanMapping.accept(ctx); } ctx.end(); return ctx.beanMappers.values(); } /** * Initializes the BeanMapping Context. * @author thanh_vucong * */ private class Context extends MappingVisitor { private BeanMapping beanMapping; private SetMap<BeanMapping, MethodMapper.Create> createMethods; private Map<BeanMapping, ObjectMapper<?>> beanMappers; private Class<? extends ObjectContext> contextType; Set<MethodMapper<?>> methodMappers; Set<PropertyMapper<?, ?, ?, ?>> propertyMappers; public void start() { this.beanMappers = new HashMap<BeanMapping, ObjectMapper<?>>(); this.createMethods = new SetMap<BeanMapping, MethodMapper.Create>(); } @Override public void startBean(BeanMapping mapping) { this.beanMapping = mapping; this.contextType = mapping.getNodeTypeKind() == NodeTypeKind.PRIMARY ? EntityContext.class : EmbeddedContext.class; this.propertyMappers = new HashSet<PropertyMapper<?, ?, ?, ?>>(); this.methodMappers = new HashSet<MethodMapper<?>>(); } @Override public void singleValueMapping(ValueMapping<ValueKind.Single> mapping) { if (mapping.getValue().getValueKind() == ValueKind.SINGLE) { SimpleTypeProvider vt = valueTypeFactory.create(mapping.getValue().getDeclaredType(), mapping.getPropertyDefinition().getMetaType()); JCRPropertySingleValuedPropertyMapper mapper = new JCRPropertySingleValuedPropertyMapper(contextType, vt, mapping); propertyMappers.add(mapper); } else { SimpleTypeProvider vt = valueTypeFactory.create(mapping.getValue().getDeclaredType(), mapping.getPropertyDefinition().getMetaType()); JCRPropertyMultiValuedPropertyMapper mapper = new JCRPropertyMultiValuedPropertyMapper(contextType, vt, mapping); propertyMappers.add(mapper); } } @Override public void multiValueMapping(ValueMapping<ValueKind.Multi> mapping) { } @Override public void oneToOneHierarchic(RelationshipMapping.OneToOne.Hierarchic mapping) { try { if (mapping.isOwner()) { JCRNamedChildParentPropertyMapper mapper = new JCRNamedChildParentPropertyMapper(contextType, mapping); propertyMappers.add(mapper); } else { JCRNamedChildPropertyMapper mapper = new JCRNamedChildPropertyMapper(mapping); propertyMappers.add(mapper); } } catch (ClassNotFoundException e) { throw new UnsupportedOperationException(e); } } @Override public void oneToManyHierarchic(RelationshipMapping.OneToMany.Hierarchic mapping) { AnyChildMultiValueMapper valueMapper; ValueKind valueKind = mapping.getProperty().getValueKind(); if (valueKind instanceof ValueKind.Map) { valueMapper = new AnyChildMultiValueMapper.Map(); } else if (valueKind instanceof ValueKind.List) { valueMapper = new AnyChildMultiValueMapper.List(); } else if (valueKind instanceof ValueKind.Collection) { valueMapper = new AnyChildMultiValueMapper.Collection(); } else { throw new AssertionError(); } try { JCRAnyChildParentPropertyMapper mapper = new JCRAnyChildParentPropertyMapper(contextType, mapping, valueMapper); propertyMappers.add(mapper); } catch (ClassNotFoundException e) { throw new UnsupportedOperationException(e); } } @Override public void manyToOneHierarchic(RelationshipMapping.ManyToOne.Hierarchic mapping) { try { JCRAnyChildCollectionPropertyMapper mapper = new JCRAnyChildCollectionPropertyMapper(mapping); propertyMappers.add(mapper); } catch (ClassNotFoundException e) { throw new UnsupportedOperationException(e); } } @Override public void oneToManyReference(RelationshipMapping.OneToMany.Reference mapping) { try { JCRReferentCollectionPropertyMapper mapper = new JCRReferentCollectionPropertyMapper(mapping); propertyMappers.add(mapper); } catch (ClassNotFoundException e) { throw new UnsupportedOperationException(e); } } @Override public void manyToOneReference(RelationshipMapping.ManyToOne.Reference mapping) { try { JCRNamedReferentPropertyMapper mapper = new JCRNamedReferentPropertyMapper(contextType, mapping); propertyMappers.add(mapper); } catch (ClassNotFoundException e) { throw new UnsupportedOperationException(e); } } @Override public void oneToOneEmbedded(RelationshipMapping.OneToOne.Embedded mapping) { try { if (mapping.isOwner()) { JCREmbeddedParentPropertyMapper mapper = new JCREmbeddedParentPropertyMapper(mapping); propertyMappers.add(mapper); } else { JCREmbeddedPropertyMapper mapper = new JCREmbeddedPropertyMapper(mapping); propertyMappers.add(mapper); } } catch (ClassNotFoundException e) { throw new UnsupportedOperationException(e); } } @Override public void propertiesMapping(PropertiesMapping<?> mapping) { JCRPropertyDetypedPropertyMapper mapper = new JCRPropertyDetypedPropertyMapper(contextType, mapping); propertyMappers.add(mapper); } @Override public void attributeMapping(AttributeMapping mapping) { JCRNodeAttributePropertyMapper mapper = new JCRNodeAttributePropertyMapper(mapping); propertyMappers.add(mapper); } @Override public void visit(CreateMapping mapping) { MethodMapper.Create mapper = new MethodMapper.Create(mapping.getMethod()); methodMappers.add(mapper); createMethods.get(mapping.getBeanMapping()).add(mapper); } @Override public void visit(DestroyMapping mapping) { MethodMapper mapper = new MethodMapper.Destroy(mapping.getMethod()); methodMappers.add(mapper); } @Override public void visit(FindByIdMapping mapping) { try { MethodMapper mapper = new MethodMapper.FindById(mapping.getMethod(), mapping.getType()); methodMappers.add(mapper); } catch (ClassNotFoundException e) { throw new UnsupportedOperationException(e); } } @Override public void endBean() { ObjectMapper<?> mapper; if (beanMapping.getNodeTypeKind() == NodeTypeKind.PRIMARY) { // Get the formatter ObjectFormatter formatter = null; if (beanMapping.getFormatterClassType() != null) { Class<? extends ObjectFormatter> formatterClass = (Class<ObjectFormatter>)beanMapping.getFormatterClassType().unwrap(); formatter = ObjectInstantiator.newInstance(formatterClass); } mapper = new ObjectMapper( beanMapping, beanMapping.isAbstract(), (Class<?>)beanMapping.getBean().getClassType().unwrap(), propertyMappers, methodMappers, beanMapping.getOnDuplicate(), formatter, beanMapping.getNodeTypeName(), beanMapping.getNodeTypeKind() ); } else { mapper = new ObjectMapper( beanMapping, beanMapping.isAbstract(), (Class<?>)beanMapping.getBean().getClassType().unwrap(), propertyMappers, methodMappers, beanMapping.getOnDuplicate(), null, beanMapping.getNodeTypeName(), beanMapping.getNodeTypeKind() ); } // beanMappers.put(beanMapping, mapper); } public void end() { for (BeanMapping beanMapping : createMethods.keySet()) { ObjectMapper beanMapper = beanMappers.get(beanMapping); for (MethodMapper.Create createMapper : createMethods.get(beanMapping)) { createMapper.mapper = beanMapper ; } } } } }