Search in sources :

Example 21 with ViewToEntityMapper

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

the class CollectionAttributeFlusher method visitInverseElementFlushersForActions.

private void visitInverseElementFlushersForActions(UpdateContext context, Iterable<?> current, Map<Object, Object> added, Map<Object, Object> removed, ElementChangeListener<E, V> listener) {
    if (elementDescriptor.isSubview()) {
        final ViewToEntityMapper mapper = elementDescriptor.getViewToEntityMapper();
        AttributeAccessor idAccessor = elementDescriptor.isIdentifiable() ? elementDescriptor.getLoadOnlyViewToEntityMapper().getViewIdAccessor() : PassthroughAttributeAccessor.INSTANCE;
        // First remove elements, then persist, otherwise we might get a constrain violation
        for (Object element : removed.values()) {
            listener.onRemovedInverseElement(element);
        }
        if (elementDescriptor.shouldFlushMutations()) {
            final Iterator<Object> iter = getRecordingIterator((V) current);
            try {
                while (iter.hasNext()) {
                    Object elem = iter.next();
                    if (elem instanceof MutableStateTrackable) {
                        MutableStateTrackable element = (MutableStateTrackable) elem;
                        @SuppressWarnings("unchecked") DirtyAttributeFlusher<?, E, V> flusher = (DirtyAttributeFlusher<?, E, V>) (DirtyAttributeFlusher) mapper.getNestedDirtyFlusher(context, element, (DirtyAttributeFlusher) null);
                        if (flusher != null) {
                            Object id = idAccessor.getValue(element);
                            if (id == null) {
                                id = element;
                            }
                            Object addedElement = added.remove(id);
                            if (addedElement != null) {
                                listener.onAddedAndUpdatedInverseElement(flusher, element);
                            } else {
                                listener.onUpdatedInverseElement(flusher, element);
                            }
                        }
                    }
                }
            } finally {
                resetRecordingIterator((V) current);
            }
        }
        // Non-dirty added values
        for (Object element : added.values()) {
            listener.onAddedInverseElement(element);
        }
    } else if (elementDescriptor.isJpaEntity()) {
        AttributeAccessor idAccessor = elementDescriptor.getLoadOnlyViewToEntityMapper().getEntityIdAccessor();
        for (Object element : removed.values()) {
            listener.onRemovedInverseElement(element);
        }
        for (Object element : current) {
            if (elementDescriptor.getBasicUserType().shouldPersist(element) && elementDescriptor.shouldJpaPersist()) {
                CollectionElementAttributeFlusher<E, V> flusher = new PersistCollectionElementAttributeFlusher<>(element, optimisticLockProtected);
                Object id = idAccessor.getValue(element);
                if (id == null) {
                    id = element;
                }
                Object addedElement = added.remove(id);
                if (addedElement != null) {
                    listener.onAddedAndUpdatedInverseElement(flusher, element);
                } else {
                    listener.onUpdatedInverseElement(flusher, element);
                }
            } else if (elementDescriptor.shouldJpaMerge()) {
                if (element != null) {
                    // Although we can't replace the original object in the backing collection, we don't care in case of inverse collections
                    CollectionElementAttributeFlusher<E, V> flusher = new MergeCollectionElementAttributeFlusher<>(element, optimisticLockProtected);
                    Object id = idAccessor.getValue(element);
                    if (id == null) {
                        id = element;
                    }
                    Object addedElement = added.remove(id);
                    if (addedElement != null) {
                        listener.onAddedAndUpdatedInverseElement(flusher, element);
                    } else {
                        listener.onUpdatedInverseElement(flusher, element);
                    }
                }
            } else {
                Object id = idAccessor.getValue(element);
                if (id == null) {
                    id = element;
                }
                Object addedElement = added.remove(id);
                if (addedElement != null) {
                    listener.onAddedInverseElement(element);
                }
            }
        }
    } else {
        throw new UnsupportedOperationException("Not yet implemented!");
    }
}
Also used : MutableStateTrackable(com.blazebit.persistence.view.spi.type.MutableStateTrackable) PassthroughAttributeAccessor(com.blazebit.persistence.view.impl.accessor.PassthroughAttributeAccessor) InitialValueAttributeAccessor(com.blazebit.persistence.view.impl.accessor.InitialValueAttributeAccessor) AttributeAccessor(com.blazebit.persistence.view.impl.accessor.AttributeAccessor) ViewToEntityMapper(com.blazebit.persistence.view.impl.entity.ViewToEntityMapper)

Example 22 with ViewToEntityMapper

use of com.blazebit.persistence.view.impl.entity.ViewToEntityMapper 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

ViewToEntityMapper (com.blazebit.persistence.view.impl.entity.ViewToEntityMapper)22 MapViewToEntityMapper (com.blazebit.persistence.view.impl.entity.MapViewToEntityMapper)11 HashMap (java.util.HashMap)10 LinkedHashMap (java.util.LinkedHashMap)10 Map (java.util.Map)10 AbstractMap (java.util.AbstractMap)8 RecordingMap (com.blazebit.persistence.view.impl.collection.RecordingMap)7 IdentityHashMap (java.util.IdentityHashMap)7 EntityMetamodel (com.blazebit.persistence.parser.EntityMetamodel)4 AttributeAccessor (com.blazebit.persistence.view.impl.accessor.AttributeAccessor)4 LoadOrPersistViewToEntityMapper (com.blazebit.persistence.view.impl.entity.LoadOrPersistViewToEntityMapper)4 ManagedViewType (com.blazebit.persistence.view.metamodel.ManagedViewType)4 MutableStateTrackable (com.blazebit.persistence.view.spi.type.MutableStateTrackable)4 ArrayList (java.util.ArrayList)4 ExtendedAttribute (com.blazebit.persistence.spi.ExtendedAttribute)3 ExtendedManagedType (com.blazebit.persistence.spi.ExtendedManagedType)3 InitialValueAttributeAccessor (com.blazebit.persistence.view.impl.accessor.InitialValueAttributeAccessor)3 EmbeddableUpdaterBasedViewToEntityMapper (com.blazebit.persistence.view.impl.entity.EmbeddableUpdaterBasedViewToEntityMapper)3 LoadOnlyViewToEntityMapper (com.blazebit.persistence.view.impl.entity.LoadOnlyViewToEntityMapper)3 UpdaterBasedViewToEntityMapper (com.blazebit.persistence.view.impl.entity.UpdaterBasedViewToEntityMapper)3