Search in sources :

Example 1 with RecordingList

use of com.blazebit.persistence.view.impl.collection.RecordingList in project blaze-persistence by Blazebit.

the class EntityViewUpdaterImpl method createPluralAttributeFlusher.

private DirtyAttributeFlusher<?, ?, ?> createPluralAttributeFlusher(EntityViewManagerImpl evm, Map<Object, EntityViewUpdaterImpl> localCache, ManagedViewTypeImplementor<?> viewType, String idAttributeName, FlushStrategy flushStrategy, AbstractMethodAttribute<?, ?> attribute, DirtyAttributeFlusher<?, ?, ?> ownerIdFlusher, EntityViewUpdaterImpl owner, String ownerMapping) {
    EntityMetamodel entityMetamodel = evm.getMetamodel().getEntityMetamodel();
    Class<?> entityClass = viewType.getEntityClass();
    ExtendedManagedType managedType = entityMetamodel.getManagedType(ExtendedManagedType.class, entityClass);
    String attributeName = attribute.getName();
    String attributeMapping = attribute.getMapping();
    AttributeAccessor entityAttributeAccessor = Accessors.forEntityMapping(evm, attribute);
    boolean cascadeDelete = attribute.isDeleteCascaded();
    boolean viewOnlyDeleteCascaded = cascadeDelete && !managedType.getAttribute(attributeMapping).isDeleteCascaded();
    boolean optimisticLockProtected = attribute.isOptimisticLockProtected();
    JpaProvider jpaProvider = evm.getJpaProvider();
    PluralAttribute<?, ?, ?> pluralAttribute = (PluralAttribute<?, ?, ?>) attribute;
    InitialValueAttributeAccessor viewAttributeAccessor = Accessors.forMutableViewAttribute(evm, attribute);
    ManagedType<?> ownerManagedType = owner == null ? viewType.getJpaManagedType() : owner.managedViewType.getJpaManagedType();
    EntityType<?> ownerEntityType = ownerManagedType instanceof EntityType<?> ? (EntityType<?>) ownerManagedType : null;
    DirtyAttributeFlusher<?, ?, ?> attributeOwnerFlusher;
    if (attributeMapping == null || ownerEntityType == null) {
        // In case of cascading only attributes i.e. correlations, we use the owner id flusher as it's not updatable anyway
        attributeOwnerFlusher = ownerIdFlusher;
    } else {
        Map<String, String> joinTableOwnerProperties;
        if (ownerMapping == null) {
            joinTableOwnerProperties = jpaProvider.getJoinMappingPropertyNames(ownerEntityType, ownerMapping, attributeMapping);
        } else {
            joinTableOwnerProperties = jpaProvider.getJoinMappingPropertyNames(ownerEntityType, ownerMapping, ownerMapping + "." + attributeMapping);
        }
        if (joinTableOwnerProperties.size() != 1) {
            String idMapping = ownerIdFlusher.getMapping();
            String prefix;
            if (idMapping.endsWith(".")) {
                prefix = idMapping;
            } else {
                prefix = idMapping + ".";
            }
            for (String joinTableOwnerProperty : joinTableOwnerProperties.keySet()) {
                if (!joinTableOwnerProperty.startsWith(prefix)) {
                    throw new IllegalArgumentException("Multiple joinable owner properties for attribute '" + attributeName + "' of " + ownerEntityType.getJavaType().getName() + " found which is not yet supported. Consider using the primary key instead!");
                }
            }
            attributeOwnerFlusher = ownerIdFlusher;
        } else if (ownerIdFlusher.getMapping().equals(joinTableOwnerProperties.values().iterator().next())) {
            attributeOwnerFlusher = ownerIdFlusher;
        } else {
            attributeOwnerFlusher = findSingularAttributeFlusherByMapping(evm, localCache, owner, viewType, attributeName, joinTableOwnerProperties.keySet().iterator().next());
        }
    }
    TypeDescriptor elementDescriptor = TypeDescriptor.forType(evm, localCache, this, attribute, pluralAttribute.getElementType(), owner, ownerMapping);
    boolean collectionUpdatable = attribute.isUpdatable();
    CollectionRemoveListener elementRemoveListener = createOrphanRemoveListener(attribute, elementDescriptor);
    CollectionRemoveListener elementCascadeDeleteListener = createCascadeDeleteListener(attribute, elementDescriptor);
    boolean jpaProviderDeletesCollection;
    boolean supportsCollectionDml = jpaProvider.supportsInsertStatement();
    if (elementDescriptor.getAttributeIdAttributeName() != null) {
        jpaProviderDeletesCollection = jpaProvider.supportsJoinTableCleanupOnDelete();
    } else {
        jpaProviderDeletesCollection = jpaProvider.supportsCollectionTableCleanupOnDelete();
    }
    if (attribute instanceof MapAttribute<?, ?, ?>) {
        MapAttribute<?, ?, ?> mapAttribute = (MapAttribute<?, ?, ?>) attribute;
        TypeDescriptor keyDescriptor = TypeDescriptor.forType(evm, localCache, this, attribute, mapAttribute.getKeyType(), owner, ownerMapping);
        // TODO: currently there is no possibility to set this
        CollectionRemoveListener keyRemoveListener = null;
        CollectionRemoveListener keyCascadeDeleteListener = null;
        if (collectionUpdatable || keyDescriptor.shouldFlushMutations() || elementDescriptor.shouldFlushMutations() || shouldPassThrough(evm, viewType, attribute)) {
            MapViewToEntityMapper mapper = new SimpleMapViewToEntityMapper(keyDescriptor.getViewToEntityMapper(), elementDescriptor.getViewToEntityMapper());
            MapViewToEntityMapper loadOnlyMapper = new SimpleMapViewToEntityMapper(keyDescriptor.getLoadOnlyViewToEntityMapper(), elementDescriptor.getLoadOnlyViewToEntityMapper());
            MapInstantiatorImplementor<?, ?> mapInstantiator = attribute.getMapInstantiator();
            return new MapAttributeFlusher<Object, RecordingMap<Map<?, ?>, ?, ?>>(attributeName, attributeMapping, owner == null ? entityClass : owner.fullEntityLoader.getEntityClass(), idAttributeName, ownerMapping, attributeOwnerFlusher, createPluralAttributeSubFlusher(evm, localCache, viewType, attribute, "element", mapAttribute.getElementType(), owner, ownerMapping), supportsCollectionDml, flushStrategy, entityAttributeAccessor, viewAttributeAccessor, optimisticLockProtected, collectionUpdatable, keyCascadeDeleteListener, elementCascadeDeleteListener, keyRemoveListener, elementRemoveListener, viewOnlyDeleteCascaded, jpaProviderDeletesCollection, keyDescriptor, elementDescriptor, mapper, loadOnlyMapper, mapInstantiator);
        } else {
            return null;
        }
    } else {
        if (collectionUpdatable || elementDescriptor.shouldFlushMutations() || shouldPassThrough(evm, viewType, attribute)) {
            InverseFlusher<Object> inverseFlusher = InverseFlusher.forAttribute(evm, localCache, viewType, attribute, elementDescriptor, owner, ownerMapping);
            InverseRemoveStrategy inverseRemoveStrategy = attribute.getInverseRemoveStrategy();
            CollectionInstantiatorImplementor<?, ?> collectionInstantiator = attribute.getCollectionInstantiator();
            if (pluralAttribute.isIndexed()) {
                return new IndexedListAttributeFlusher<Object, RecordingList<List<?>>>(attributeName, attributeMapping, owner == null ? entityClass : owner.fullEntityLoader.getEntityClass(), idAttributeName, ownerMapping, attributeOwnerFlusher, createPluralAttributeSubFlusher(evm, localCache, viewType, attribute, "element", pluralAttribute.getElementType(), owner, ownerMapping), supportsCollectionDml, flushStrategy, entityAttributeAccessor, viewAttributeAccessor, optimisticLockProtected, collectionUpdatable, viewOnlyDeleteCascaded, jpaProviderDeletesCollection, elementCascadeDeleteListener, elementRemoveListener, collectionInstantiator, elementDescriptor, inverseFlusher, inverseRemoveStrategy);
            } else {
                return new CollectionAttributeFlusher(attributeName, attributeMapping, owner == null ? entityClass : owner.fullEntityLoader.getEntityClass(), idAttributeName, ownerMapping, attributeOwnerFlusher, createPluralAttributeSubFlusher(evm, localCache, viewType, attribute, "element", pluralAttribute.getElementType(), owner, ownerMapping), supportsCollectionDml, flushStrategy, entityAttributeAccessor, viewAttributeAccessor, optimisticLockProtected, collectionUpdatable, viewOnlyDeleteCascaded, jpaProviderDeletesCollection, elementCascadeDeleteListener, elementRemoveListener, collectionInstantiator, elementDescriptor, inverseFlusher, inverseRemoveStrategy);
            }
        } else {
            return null;
        }
    }
}
Also used : InitialValueAttributeAccessor(com.blazebit.persistence.view.impl.accessor.InitialValueAttributeAccessor) MapAttributeFlusher(com.blazebit.persistence.view.impl.update.flush.MapAttributeFlusher) InverseRemoveStrategy(com.blazebit.persistence.view.InverseRemoveStrategy) CollectionRemoveListener(com.blazebit.persistence.view.impl.collection.CollectionRemoveListener) ViewCollectionRemoveListener(com.blazebit.persistence.view.impl.update.flush.ViewCollectionRemoveListener) EntityCollectionRemoveListener(com.blazebit.persistence.view.impl.update.flush.EntityCollectionRemoveListener) IndexedListAttributeFlusher(com.blazebit.persistence.view.impl.update.flush.IndexedListAttributeFlusher) List(java.util.List) RecordingList(com.blazebit.persistence.view.impl.collection.RecordingList) ArrayList(java.util.ArrayList) CollectionAttributeFlusher(com.blazebit.persistence.view.impl.update.flush.CollectionAttributeFlusher) JpaProvider(com.blazebit.persistence.spi.JpaProvider) PluralAttribute(com.blazebit.persistence.view.metamodel.PluralAttribute) ExtendedManagedType(com.blazebit.persistence.spi.ExtendedManagedType) MapAttribute(com.blazebit.persistence.view.metamodel.MapAttribute) TypeDescriptor(com.blazebit.persistence.view.impl.update.flush.TypeDescriptor) SimpleMapViewToEntityMapper(com.blazebit.persistence.view.impl.update.flush.SimpleMapViewToEntityMapper) MapViewToEntityMapper(com.blazebit.persistence.view.impl.entity.MapViewToEntityMapper) InitialValueAttributeAccessor(com.blazebit.persistence.view.impl.accessor.InitialValueAttributeAccessor) AttributeAccessor(com.blazebit.persistence.view.impl.accessor.AttributeAccessor) SimpleMapViewToEntityMapper(com.blazebit.persistence.view.impl.update.flush.SimpleMapViewToEntityMapper) EntityMetamodel(com.blazebit.persistence.parser.EntityMetamodel) Map(java.util.Map) RecordingMap(com.blazebit.persistence.view.impl.collection.RecordingMap) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) TreeMap(java.util.TreeMap)

Example 2 with RecordingList

use of com.blazebit.persistence.view.impl.collection.RecordingList in project blaze-persistence by Blazebit.

the class IndexedListAttributeFlusher method getDirtyKind.

@Override
public DirtyKind getDirtyKind(V initial, V current) {
    if (current == null) {
        if (initial == null) {
            return DirtyKind.NONE;
        }
        return DirtyKind.UPDATED;
    }
    if (initial == null) {
        return DirtyKind.UPDATED;
    }
    if (initial == current) {
        if (current instanceof RecordingList<?>) {
            return super.getDirtyKind(initial, current);
        }
    } else {
        if (initial.size() != current.size()) {
            return DirtyKind.MUTATED;
        }
        if (elementDescriptor.shouldFlushMutations()) {
            if (elementDescriptor.supportsDirtyCheck()) {
                if (elementDescriptor.isSubview()) {
                    ViewToEntityMapper mapper = elementDescriptor.getViewToEntityMapper();
                    for (int i = 0; i < current.size(); i++) {
                        Object o = current.get(i);
                        if (!Objects.equals(initial.get(i), o)) {
                            return DirtyKind.MUTATED;
                        }
                        if (o instanceof DirtyStateTrackable) {
                            DirtyStateTrackable element = (DirtyStateTrackable) o;
                            if (mapper.getUpdater(o).getDirtyChecker().getDirtyKind(element, element) != DirtyKind.NONE) {
                                return DirtyKind.MUTATED;
                            }
                        }
                    }
                } else {
                    BasicUserType<Object> userType = elementDescriptor.getBasicUserType();
                    for (int i = 0; i < current.size(); i++) {
                        Object o = current.get(i);
                        if (!Objects.equals(initial.get(i), o)) {
                            return DirtyKind.MUTATED;
                        }
                        String[] dirtyProperties = userType.getDirtyProperties(o);
                        if (dirtyProperties != null) {
                            return DirtyKind.MUTATED;
                        }
                    }
                }
            } else {
                if (elementDescriptor.getBasicUserType().supportsDeepCloning()) {
                    return collectionEquals(initial, current) ? DirtyKind.NONE : DirtyKind.MUTATED;
                } else {
                    // If we don't support dirty checking we always have to assume dirtyness
                    return DirtyKind.MUTATED;
                }
            }
        } else {
            return collectionEquals(initial, current) ? DirtyKind.NONE : DirtyKind.MUTATED;
        }
    }
    return DirtyKind.NONE;
}
Also used : DirtyStateTrackable(com.blazebit.persistence.view.spi.type.DirtyStateTrackable) RecordingList(com.blazebit.persistence.view.impl.collection.RecordingList) ViewToEntityMapper(com.blazebit.persistence.view.impl.entity.ViewToEntityMapper)

Aggregations

RecordingList (com.blazebit.persistence.view.impl.collection.RecordingList)2 EntityMetamodel (com.blazebit.persistence.parser.EntityMetamodel)1 ExtendedManagedType (com.blazebit.persistence.spi.ExtendedManagedType)1 JpaProvider (com.blazebit.persistence.spi.JpaProvider)1 InverseRemoveStrategy (com.blazebit.persistence.view.InverseRemoveStrategy)1 AttributeAccessor (com.blazebit.persistence.view.impl.accessor.AttributeAccessor)1 InitialValueAttributeAccessor (com.blazebit.persistence.view.impl.accessor.InitialValueAttributeAccessor)1 CollectionRemoveListener (com.blazebit.persistence.view.impl.collection.CollectionRemoveListener)1 RecordingMap (com.blazebit.persistence.view.impl.collection.RecordingMap)1 MapViewToEntityMapper (com.blazebit.persistence.view.impl.entity.MapViewToEntityMapper)1 ViewToEntityMapper (com.blazebit.persistence.view.impl.entity.ViewToEntityMapper)1 CollectionAttributeFlusher (com.blazebit.persistence.view.impl.update.flush.CollectionAttributeFlusher)1 EntityCollectionRemoveListener (com.blazebit.persistence.view.impl.update.flush.EntityCollectionRemoveListener)1 IndexedListAttributeFlusher (com.blazebit.persistence.view.impl.update.flush.IndexedListAttributeFlusher)1 MapAttributeFlusher (com.blazebit.persistence.view.impl.update.flush.MapAttributeFlusher)1 SimpleMapViewToEntityMapper (com.blazebit.persistence.view.impl.update.flush.SimpleMapViewToEntityMapper)1 TypeDescriptor (com.blazebit.persistence.view.impl.update.flush.TypeDescriptor)1 ViewCollectionRemoveListener (com.blazebit.persistence.view.impl.update.flush.ViewCollectionRemoveListener)1 MapAttribute (com.blazebit.persistence.view.metamodel.MapAttribute)1 PluralAttribute (com.blazebit.persistence.view.metamodel.PluralAttribute)1