Search in sources :

Example 1 with InverseEntityToEntityMapper

use of com.blazebit.persistence.view.impl.entity.InverseEntityToEntityMapper in project blaze-persistence by Blazebit.

the class InverseFlusher method forAttribute.

public static <E> InverseFlusher<E> forAttribute(EntityViewManagerImpl evm, Map<Object, EntityViewUpdaterImpl> localCache, ManagedViewType<?> viewType, AbstractMethodAttribute<?, ?> attribute, TypeDescriptor childTypeDescriptor, EntityViewUpdaterImpl owner, String ownerMapping) {
    if (attribute.getMappedBy() != null) {
        String attributeLocation = attribute.getLocation();
        Type<?> elementType = attribute instanceof PluralAttribute<?, ?, ?> ? ((PluralAttribute<?, ?, ?>) attribute).getElementType() : ((SingularAttribute<?, ?>) attribute).getType();
        Class<?> elementEntityClass = null;
        AttributeAccessor parentReferenceAttributeAccessor = null;
        Mapper<Object, Object> parentEntityOnChildViewMapper = null;
        Mapper<Object, Object> parentEntityOnChildEntityAddMapper = null;
        Mapper<Object, Object> parentEntityOnChildEntityRemoveMapper = null;
        TargetViewClassBasedInverseViewToEntityMapper childViewToEntityMapper = null;
        InverseEntityToEntityMapper childEntityToEntityMapper = null;
        ViewToEntityMapper parentReferenceViewToEntityMapper = new LoadOnlyViewToEntityMapper(new ReferenceEntityLoader(evm, viewType, EntityViewUpdaterImpl.createViewIdMapper(evm, localCache, viewType)), Accessors.forViewId(evm, (ViewType<?>) viewType, true), evm.getEntityIdAccessor());
        ViewToEntityMapper childReferenceViewToEntityMapper = null;
        TypeDescriptor parentReferenceTypeDescriptor = TypeDescriptor.forInverseAttribute(parentReferenceViewToEntityMapper);
        if (attribute.getWritableMappedByMappings() != null) {
            // This happens when the mapped by attribute is insertable=false and updatable=false
            if (childTypeDescriptor.isSubview()) {
                ViewType<?> childViewType = (ViewType<?>) elementType;
                elementEntityClass = childViewType.getEntityClass();
                Map<Class<?>, Mapper<Object, Object>> mappers = new HashMap<>();
                for (ManagedViewType<?> type : attribute.getViewTypes()) {
                    Mapper<Object, Object> mapper = Mappers.forViewConvertToViewAttributeMapping(evm, (ViewType<Object>) viewType, (ViewType<Object>) type, attribute.getWritableMappedByMappings(), (Mapper<Object, Object>) Mappers.forEntityAttributeMappingConvertToViewAttributeMapping(evm, viewType.getEntityClass(), type, attribute.getWritableMappedByMappings()));
                    if (mapper == null) {
                        mapper = NoopMapper.INSTANCE;
                    }
                    mappers.put(type.getJavaType(), mapper);
                }
                parentEntityOnChildViewMapper = (Mapper<Object, Object>) Mappers.targetViewClassBasedMapper(mappers);
                parentEntityOnChildEntityAddMapper = parentEntityOnChildEntityRemoveMapper = (Mapper<Object, Object>) Mappers.forEntityAttributeMapping(evm, viewType.getEntityClass(), childViewType.getEntityClass(), attribute.getWritableMappedByMappings());
                childReferenceViewToEntityMapper = new LoadOrPersistViewToEntityMapper(attributeLocation, evm, childViewType.getJavaType(), attribute.getReadOnlyAllowedSubtypes(), attribute.getPersistCascadeAllowedSubtypes(), attribute.getUpdateCascadeAllowedSubtypes(), new ReferenceEntityLoader(evm, childViewType, EntityViewUpdaterImpl.createViewIdMapper(evm, localCache, childViewType)), Accessors.forViewId(evm, childViewType, true), evm.getEntityIdAccessor(), true, owner, ownerMapping, localCache);
            } else if (childTypeDescriptor.isJpaEntity()) {
                Class<?> childType = elementType.getJavaType();
                elementEntityClass = childType;
                parentEntityOnChildViewMapper = (Mapper<Object, Object>) Mappers.forEntityAttributeMapping(evm, viewType.getEntityClass(), childType, attribute.getWritableMappedByMappings());
                parentEntityOnChildEntityAddMapper = parentEntityOnChildEntityRemoveMapper = (Mapper<Object, Object>) Mappers.forEntityAttributeMapping(evm, viewType.getEntityClass(), elementEntityClass, attribute.getWritableMappedByMappings());
            }
        } else {
            if (childTypeDescriptor.isSubview()) {
                ViewType<?> childViewType = (ViewType<?>) elementType;
                elementEntityClass = childViewType.getEntityClass();
                parentReferenceAttributeAccessor = Accessors.forEntityMapping(evm, childViewType.getEntityClass(), attribute.getMappedBy());
                childReferenceViewToEntityMapper = new LoadOrPersistViewToEntityMapper(attributeLocation, evm, childViewType.getJavaType(), attribute.getReadOnlyAllowedSubtypes(), attribute.getPersistCascadeAllowedSubtypes(), attribute.getUpdateCascadeAllowedSubtypes(), new ReferenceEntityLoader(evm, childViewType, EntityViewUpdaterImpl.createViewIdMapper(evm, localCache, childViewType)), Accessors.forViewId(evm, childViewType, true), evm.getEntityIdAccessor(), true, owner, ownerMapping, localCache);
                parentEntityOnChildEntityAddMapper = parentEntityOnChildEntityRemoveMapper = Mappers.forAccessor(parentReferenceAttributeAccessor);
                Map<Class<?>, Mapper<Object, Object>> mappers = new HashMap<>();
                for (ManagedViewType<?> type : attribute.getViewTypes()) {
                    Mapper<Object, Object> mapper = (Mapper<Object, Object>) Mappers.forViewConvertToViewAttributeMapping(evm, (ViewType<Object>) viewType, (ViewType<Object>) type, attribute.getMappedBy(), null);
                    if (mapper == null) {
                        mapper = NoopMapper.INSTANCE;
                    }
                    mappers.put(type.getJavaType(), mapper);
                }
                parentEntityOnChildViewMapper = (Mapper<Object, Object>) Mappers.targetViewClassBasedMapper(mappers);
            } else if (childTypeDescriptor.isJpaEntity()) {
                Class<?> childType = elementType.getJavaType();
                elementEntityClass = childType;
                parentReferenceAttributeAccessor = Accessors.forEntityMapping(evm, childType, attribute.getMappedBy());
                parentEntityOnChildEntityAddMapper = parentEntityOnChildEntityRemoveMapper = Mappers.forAccessor(parentReferenceAttributeAccessor);
                parentEntityOnChildViewMapper = Mappers.forAccessor(parentReferenceAttributeAccessor);
            }
        }
        DirtyAttributeFlusher<?, Object, ? extends Object> parentReferenceAttributeFlusher;
        ManagedType<?> managedType = evm.getMetamodel().getEntityMetamodel().getManagedType(elementEntityClass);
        Attribute<?, ?> inverseAttribute = JpaMetamodelUtils.getAttribute(managedType, attribute.getMappedBy());
        // Many-To-Many relation can't be handled by the inverse flushers
        if (inverseAttribute != null && inverseAttribute.isCollection()) {
            // A collection can only have a single attribute, so it's safe to assume a SimpleMapper
            parentEntityOnChildEntityAddMapper = new CollectionAddMapper<>(parentEntityOnChildEntityAddMapper == null ? parentReferenceAttributeAccessor : ((SimpleMapper<Object, Object>) parentEntityOnChildEntityAddMapper).getAttributeAccessor());
            parentEntityOnChildEntityRemoveMapper = new CollectionRemoveMapper<>(parentEntityOnChildEntityRemoveMapper == null ? parentReferenceAttributeAccessor : ((SimpleMapper<Object, Object>) parentEntityOnChildEntityRemoveMapper).getAttributeAccessor());
            parentReferenceAttributeFlusher = new ParentCollectionReferenceAttributeFlusher<>(attributeLocation, attribute.getMappedBy(), viewType.getFlushStrategy(), parentReferenceAttributeAccessor, null, null, null, TypeDescriptor.forInverseCollectionAttribute(viewType.getEntityClass(), new EntityBasicUserType(evm.getJpaProvider())));
        } else {
            parentEntityOnChildEntityRemoveMapper = new NullMapper<>(parentEntityOnChildEntityRemoveMapper);
            parentReferenceAttributeFlusher = new ParentReferenceAttributeFlusher<>(evm, viewType.getEntityClass(), attributeLocation, attribute.getMappedBy(), attribute.getWritableMappedByMappings(), parentReferenceTypeDescriptor, parentReferenceAttributeAccessor, parentEntityOnChildViewMapper);
        }
        UnmappedAttributeCascadeDeleter deleter = null;
        String parentIdAttributeName = null;
        String childIdAttributeName = null;
        Class<?> childIdViewClass = null;
        // Only construct when orphanRemoval or delete cascading is enabled, orphanRemoval implies delete cascading
        if (attribute.isDeleteCascaded()) {
            EntityMetamodel entityMetamodel = evm.getMetamodel().getEntityMetamodel();
            ExtendedManagedType<?> ownerManagedType = entityMetamodel.getManagedType(ExtendedManagedType.class, viewType.getEntityClass());
            ExtendedManagedType<?> elementManagedType = entityMetamodel.getManagedType(ExtendedManagedType.class, elementEntityClass);
            parentIdAttributeName = ownerManagedType.getIdAttribute().getName();
            childIdAttributeName = elementManagedType.getIdAttribute().getName();
            String mapping = attribute.getMappedBy();
            if (mapping != null) {
                if (mapping.isEmpty()) {
                    deleter = new UnmappedWritableBasicAttributeSetNullCascadeDeleter(evm, ownerManagedType.getType(), elementManagedType, attribute.getWritableMappedByMappings());
                } else {
                    ExtendedAttribute extendedAttribute = elementManagedType.getAttribute(mapping);
                    if (childTypeDescriptor.isSubview()) {
                        if (elementType instanceof ViewType<?>) {
                            MethodAttribute<?, ?> idAttribute = ((ViewType<?>) elementType).getIdAttribute();
                            if (idAttribute.isSubview()) {
                                // in this case, we need to fetch the id as view as the deleter expects it this way
                                childIdViewClass = idAttribute.getJavaType();
                            }
                        }
                        deleter = new ViewTypeCascadeDeleter(childTypeDescriptor.getViewToEntityMapper());
                    } else if (childTypeDescriptor.isJpaEntity()) {
                        deleter = new UnmappedBasicAttributeCascadeDeleter(evm, mapping, extendedAttribute, mapping + "." + parentIdAttributeName, false);
                    }
                }
            }
        }
        if (childTypeDescriptor.isSubview()) {
            InverseViewToEntityMapper<?> first = null;
            Map<Class<?>, InverseViewToEntityMapper<?>> mappers = new HashMap<>();
            for (ManagedViewType<?> type : attribute.getViewTypes()) {
                InverseViewToEntityMapper inverseViewToEntityMapper = new InverseViewToEntityMapper(evm, localCache, (ViewType<?>) type, parentEntityOnChildViewMapper, parentEntityOnChildEntityAddMapper, parentEntityOnChildEntityRemoveMapper, childTypeDescriptor.getViewToEntityMapper(), parentReferenceAttributeFlusher, EntityViewUpdaterImpl.createIdFlusher(evm, localCache, (ViewType<?>) type, EntityViewUpdaterImpl.createViewIdMapper(evm, localCache, type)));
                mappers.put(type.getJavaType(), inverseViewToEntityMapper);
                if (type == elementType) {
                    first = inverseViewToEntityMapper;
                }
            }
            childViewToEntityMapper = new TargetViewClassBasedInverseViewToEntityMapper(first, mappers);
        } else if (childTypeDescriptor.isJpaEntity()) {
            Class<?> childType = elementType.getJavaType();
            childEntityToEntityMapper = new InverseEntityToEntityMapper(evm, evm.getMetamodel().getEntityMetamodel().entity(childType), parentEntityOnChildEntityAddMapper, parentEntityOnChildEntityRemoveMapper, parentReferenceAttributeFlusher);
        }
        return new InverseFlusher(viewType.getEntityClass(), attribute.getMapping(), parentIdAttributeName, childIdAttributeName, childIdViewClass, deleter, parentReferenceViewToEntityMapper, parentReferenceAttributeFlusher, parentEntityOnChildViewMapper, childViewToEntityMapper, childReferenceViewToEntityMapper, parentEntityOnChildEntityAddMapper, childEntityToEntityMapper);
    }
    return null;
}
Also used : LoadOrPersistViewToEntityMapper(com.blazebit.persistence.view.impl.entity.LoadOrPersistViewToEntityMapper) LoadOnlyViewToEntityMapper(com.blazebit.persistence.view.impl.entity.LoadOnlyViewToEntityMapper) HashMap(java.util.HashMap) CollectionRemoveMapper(com.blazebit.persistence.view.impl.mapper.CollectionRemoveMapper) LoadOrPersistViewToEntityMapper(com.blazebit.persistence.view.impl.entity.LoadOrPersistViewToEntityMapper) LoadOnlyViewToEntityMapper(com.blazebit.persistence.view.impl.entity.LoadOnlyViewToEntityMapper) NoopMapper(com.blazebit.persistence.view.impl.mapper.NoopMapper) InverseEntityToEntityMapper(com.blazebit.persistence.view.impl.entity.InverseEntityToEntityMapper) NullMapper(com.blazebit.persistence.view.impl.mapper.NullMapper) CollectionAddMapper(com.blazebit.persistence.view.impl.mapper.CollectionAddMapper) TargetViewClassBasedInverseViewToEntityMapper(com.blazebit.persistence.view.impl.entity.TargetViewClassBasedInverseViewToEntityMapper) InverseElementToEntityMapper(com.blazebit.persistence.view.impl.entity.InverseElementToEntityMapper) Mapper(com.blazebit.persistence.view.impl.mapper.Mapper) SimpleMapper(com.blazebit.persistence.view.impl.mapper.SimpleMapper) ViewToEntityMapper(com.blazebit.persistence.view.impl.entity.ViewToEntityMapper) InverseViewToEntityMapper(com.blazebit.persistence.view.impl.entity.InverseViewToEntityMapper) LoadOrPersistViewToEntityMapper(com.blazebit.persistence.view.impl.entity.LoadOrPersistViewToEntityMapper) LoadOnlyViewToEntityMapper(com.blazebit.persistence.view.impl.entity.LoadOnlyViewToEntityMapper) TargetViewClassBasedInverseViewToEntityMapper(com.blazebit.persistence.view.impl.entity.TargetViewClassBasedInverseViewToEntityMapper) ViewToEntityMapper(com.blazebit.persistence.view.impl.entity.ViewToEntityMapper) InverseViewToEntityMapper(com.blazebit.persistence.view.impl.entity.InverseViewToEntityMapper) TargetViewClassBasedInverseViewToEntityMapper(com.blazebit.persistence.view.impl.entity.TargetViewClassBasedInverseViewToEntityMapper) TargetViewClassBasedInverseViewToEntityMapper(com.blazebit.persistence.view.impl.entity.TargetViewClassBasedInverseViewToEntityMapper) InverseViewToEntityMapper(com.blazebit.persistence.view.impl.entity.InverseViewToEntityMapper) ExtendedAttribute(com.blazebit.persistence.spi.ExtendedAttribute) ReferenceEntityLoader(com.blazebit.persistence.view.impl.entity.ReferenceEntityLoader) InverseEntityToEntityMapper(com.blazebit.persistence.view.impl.entity.InverseEntityToEntityMapper) EntityBasicUserType(com.blazebit.persistence.view.impl.type.EntityBasicUserType) AttributeAccessor(com.blazebit.persistence.view.impl.accessor.AttributeAccessor) EntityMetamodel(com.blazebit.persistence.parser.EntityMetamodel) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) ViewType(com.blazebit.persistence.view.metamodel.ViewType)

Aggregations

EntityMetamodel (com.blazebit.persistence.parser.EntityMetamodel)1 ExtendedAttribute (com.blazebit.persistence.spi.ExtendedAttribute)1 AttributeAccessor (com.blazebit.persistence.view.impl.accessor.AttributeAccessor)1 InverseElementToEntityMapper (com.blazebit.persistence.view.impl.entity.InverseElementToEntityMapper)1 InverseEntityToEntityMapper (com.blazebit.persistence.view.impl.entity.InverseEntityToEntityMapper)1 InverseViewToEntityMapper (com.blazebit.persistence.view.impl.entity.InverseViewToEntityMapper)1 LoadOnlyViewToEntityMapper (com.blazebit.persistence.view.impl.entity.LoadOnlyViewToEntityMapper)1 LoadOrPersistViewToEntityMapper (com.blazebit.persistence.view.impl.entity.LoadOrPersistViewToEntityMapper)1 ReferenceEntityLoader (com.blazebit.persistence.view.impl.entity.ReferenceEntityLoader)1 TargetViewClassBasedInverseViewToEntityMapper (com.blazebit.persistence.view.impl.entity.TargetViewClassBasedInverseViewToEntityMapper)1 ViewToEntityMapper (com.blazebit.persistence.view.impl.entity.ViewToEntityMapper)1 CollectionAddMapper (com.blazebit.persistence.view.impl.mapper.CollectionAddMapper)1 CollectionRemoveMapper (com.blazebit.persistence.view.impl.mapper.CollectionRemoveMapper)1 Mapper (com.blazebit.persistence.view.impl.mapper.Mapper)1 NoopMapper (com.blazebit.persistence.view.impl.mapper.NoopMapper)1 NullMapper (com.blazebit.persistence.view.impl.mapper.NullMapper)1 SimpleMapper (com.blazebit.persistence.view.impl.mapper.SimpleMapper)1 EntityBasicUserType (com.blazebit.persistence.view.impl.type.EntityBasicUserType)1 ManagedViewType (com.blazebit.persistence.view.metamodel.ManagedViewType)1 ViewType (com.blazebit.persistence.view.metamodel.ViewType)1