Search in sources :

Example 1 with MapAction

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

the class ResetInitialStateSynchronization method afterCompletion.

@Override
@SuppressWarnings("unchecked")
public void afterCompletion(int status) {
    if (status != Status.STATUS_COMMITTED) {
        Map<EntityViewProxy, ViewTransition> objects;
        if (listenerManager.hasPostRollbackListeners()) {
            objects = new IdentityHashMap<>();
        } else {
            objects = null;
        }
        if (coalescedInitialStates != null) {
            for (int i = 0; i < coalescedInitialStates.size(); i += 2) {
                Object[] initialState = coalescedInitialStates.get(i);
                Object[] originalInitialState = coalescedInitialStates.get(i + 1);
                for (int j = 0; j < initialState.length; j++) {
                    initialState[j] = originalInitialState[j];
                }
            }
        }
        if (coalescedRecordingActions != null) {
            for (int i = 0; i < coalescedRecordingActions.size(); i += 4) {
                Object collectionReference = coalescedRecordingActions.get(i);
                Object actionList = coalescedRecordingActions.get(i + 1);
                Map<Object, Object> added = (Map<Object, Object>) coalescedRecordingActions.get(i + 2);
                Map<Object, Object> removed = (Map<Object, Object>) coalescedRecordingActions.get(i + 3);
                if (collectionReference instanceof RecordingCollection<?, ?>) {
                    RecordingCollection<Collection<Object>, Object> collection = (RecordingCollection<Collection<Object>, Object>) collectionReference;
                    collection.setActions((List<CollectionAction<Collection<Object>>>) (List<?>) actionList, added, removed);
                    collection.$$_markDirty(-1);
                } else {
                    Map<Object, Object> addedElements = (Map<Object, Object>) coalescedRecordingActions.get(i + 4);
                    Map<Object, Object> removedElements = (Map<Object, Object>) coalescedRecordingActions.get(i + 5);
                    RecordingMap<Map<Object, Object>, Object, Object> collection = (RecordingMap<Map<Object, Object>, Object, Object>) collectionReference;
                    collection.setActions((List<MapAction<Map<Object, Object>>>) (List<?>) actionList, added, removed, addedElements, removedElements);
                    collection.$$_markDirty(-1);
                    i += 2;
                }
            }
        }
        if (persistedViews != null) {
            for (int i = 0; i < persistedViews.size(); i += 7) {
                MutableStateTrackable view = (MutableStateTrackable) persistedViews.get(i);
                Object newObject = persistedViews.get(i + 1);
                view.$$_setIsNew(true);
                Object id = persistedViews.get(i + 2);
                DirtyTracker parent = (DirtyTracker) persistedViews.get(i + 3);
                int parentIndex = (int) persistedViews.get(i + 4);
                List<Object> readOnlyParents = (List<Object>) persistedViews.get(i + 5);
                if (id != NO_ID_MARKER) {
                    view.$$_setId(id);
                }
                if (parent != null) {
                    // This is not needed as this will happen when rolling back collection actions already
                    if (!(parent instanceof RecordingCollection<?, ?> || parent instanceof RecordingMap<?, ?, ?>)) {
                        parent.$$_replaceAttribute(newObject, parentIndex, view);
                    }
                    for (int j = 0; j < readOnlyParents.size(); j += 2) {
                        DirtyTracker readOnlyParent = (DirtyTracker) readOnlyParents.get(j);
                        int readOnlyParentIndex = (int) readOnlyParents.get(j + 1);
                        readOnlyParent.$$_replaceAttribute(newObject, readOnlyParentIndex, view);
                    }
                }
                view.$$_setDirty((long[]) persistedViews.get(i + 6));
                if (objects != null) {
                    objects.put(view, ViewTransition.PERSIST);
                }
            }
        }
        if (updatedViews != null) {
            for (int i = 0; i < updatedViews.size(); i += 2) {
                MutableStateTrackable view = (MutableStateTrackable) updatedViews.get(i);
                view.$$_setDirty((long[]) updatedViews.get(i + 1));
                if (objects != null) {
                    objects.put(view, ViewTransition.UPDATE);
                }
            }
        }
        if (removedViews != null) {
            for (int i = 0; i < removedViews.size(); i += 4) {
                EntityViewProxy view = (EntityViewProxy) removedViews.get(i);
                if (view instanceof MutableStateTrackable) {
                    MutableStateTrackable removedView = (MutableStateTrackable) view;
                    DirtyTracker parent = (DirtyTracker) removedViews.get(i + 1);
                    if (parent != null) {
                        removedView.$$_setParent(parent, (Integer) removedViews.get(i + 2));
                    }
                    long[] dirtyArray = (long[]) removedViews.get(i + 3);
                    if (dirtyArray != null) {
                        removedView.$$_setDirty(dirtyArray);
                    }
                }
                if (objects != null) {
                    objects.put(view, ViewTransition.REMOVE);
                }
            }
        }
        if (versionedViews != null) {
            for (int i = 0; i < versionedViews.size(); i += 2) {
                MutableStateTrackable view = (MutableStateTrackable) versionedViews.get(i);
                view.$$_setVersion(versionedViews.get(i + 1));
            }
        }
        if (objects != null) {
            PostRollbackInvoker postRollbackInvoker = new PostRollbackInvoker(updateContext, listenerManager, objects);
            TransactionSupport txSupport = updateContext.getEntityViewManager().getService(TransactionSupport.class);
            if (txSupport == null) {
                TransactionAccess transactionAccess = updateContext.getTransactionAccess();
                if (transactionAccess instanceof SynchronizationRegistry) {
                    transactionAccess = ((SynchronizationRegistry) transactionAccess).getTransactionAccess();
                }
                if (transactionAccess instanceof TransactionSupport) {
                    ((TransactionSupport) transactionAccess).transactional(postRollbackInvoker);
                } else {
                    // Log warning that querying doesn't work because we can't run in a new transaction?
                    postRollbackInvoker.run();
                }
            } else {
                txSupport.transactional(postRollbackInvoker);
            }
        }
    } else {
        if (listenerManager.hasPostCommitListeners()) {
            if (persistedViews != null) {
                for (int i = 0; i < persistedViews.size(); i += 7) {
                    listenerManager.invokePostCommit(updateContext, (MutableStateTrackable) persistedViews.get(i), ViewTransition.PERSIST);
                }
            }
            if (updatedViews != null) {
                for (int i = 0; i < updatedViews.size(); i += 2) {
                    listenerManager.invokePostCommit(updateContext, (MutableStateTrackable) updatedViews.get(i), ViewTransition.UPDATE);
                }
            }
            if (removedViews != null) {
                for (int i = 0; i < removedViews.size(); i += 4) {
                    listenerManager.invokePostCommit(updateContext, (EntityViewProxy) removedViews.get(i), ViewTransition.REMOVE);
                }
            }
        }
    }
}
Also used : MutableStateTrackable(com.blazebit.persistence.view.spi.type.MutableStateTrackable) ViewTransition(com.blazebit.persistence.view.ViewTransition) RecordingCollection(com.blazebit.persistence.view.impl.collection.RecordingCollection) TransactionSupport(com.blazebit.persistence.view.spi.TransactionSupport) EntityViewProxy(com.blazebit.persistence.view.spi.type.EntityViewProxy) ArrayList(java.util.ArrayList) List(java.util.List) DirtyTracker(com.blazebit.persistence.view.spi.type.DirtyTracker) RecordingMap(com.blazebit.persistence.view.impl.collection.RecordingMap) MapAction(com.blazebit.persistence.view.impl.collection.MapAction) SynchronizationRegistry(com.blazebit.persistence.view.impl.tx.SynchronizationRegistry) TransactionAccess(com.blazebit.persistence.view.spi.TransactionAccess) CollectionAction(com.blazebit.persistence.view.impl.collection.CollectionAction) RecordingCollection(com.blazebit.persistence.view.impl.collection.RecordingCollection) Collection(java.util.Collection) IdentityHashMap(java.util.IdentityHashMap) Map(java.util.Map) RecordingMap(com.blazebit.persistence.view.impl.collection.RecordingMap)

Example 2 with MapAction

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

the class MapAttributeFlusher method determineJpaCollectionActions.

protected List<MapAction<Map<Object, Object>>> determineJpaCollectionActions(UpdateContext context, V initial, V current, EqualityChecker equalityChecker) {
    List<MapAction<Map<Object, Object>>> actions = new ArrayList<>();
    Map.Entry<Object, Object>[] objectsToAdd = (Map.Entry<Object, Object>[]) current.entrySet().toArray(new Map.Entry[current.size()]);
    if (keyDescriptor.isSubview() && keyDescriptor.isIdentifiable()) {
        final AttributeAccessor entityIdAccessor = keyDescriptor.getViewToEntityMapper().getEntityIdAccessor();
        final AttributeAccessor subviewIdAccessor = keyDescriptor.getViewToEntityMapper().getViewIdAccessor();
        OUTER: for (Map.Entry<?, ?> entry : initial.entrySet()) {
            Object initialObject = entry.getKey();
            Object initialViewId = entityIdAccessor.getValue(initialObject);
            Object initialElement = getViewElement(context, elementDescriptor, entry.getValue());
            for (int i = 0; i < objectsToAdd.length; i++) {
                Map.Entry<Object, Object> entryToAdd = objectsToAdd[i];
                Object currentObject = entryToAdd.getKey();
                if (currentObject != REMOVED_MARKER) {
                    Object currentViewId = subviewIdAccessor.getValue(currentObject);
                    if (initialViewId.equals(currentViewId)) {
                        objectsToAdd[i] = REMOVED_MARKER;
                        if (!equalityChecker.isEqual(context, entry.getValue(), entryToAdd.getValue())) {
                            if (keyDescriptor.shouldFlushMutations()) {
                                actions.add((MapAction<Map<Object, Object>>) (MapAction<?>) new MapRemoveAction<>(initialObject, initialElement));
                            }
                            actions.add((MapAction<Map<Object, Object>>) (MapAction<?>) new MapPutAction<>(entryToAdd.getKey(), entryToAdd.getValue(), initialElement));
                        }
                        continue OUTER;
                    }
                }
            }
            actions.add((MapAction<Map<Object, Object>>) (MapAction<?>) new MapRemoveAction<>(initialObject, initialElement));
        }
    } else {
        final BasicUserType<Object> basicUserType = keyDescriptor.getBasicUserType();
        OUTER: for (Map.Entry<?, ?> entry : initial.entrySet()) {
            Object initialObject = entry.getKey();
            Object initialElement = getViewElement(context, elementDescriptor, entry.getValue());
            for (int i = 0; i < objectsToAdd.length; i++) {
                Map.Entry<Object, Object> entryToAdd = objectsToAdd[i];
                Object currentObject = entryToAdd.getKey();
                if (currentObject != REMOVED_MARKER) {
                    if (basicUserType.isEqual(initialObject, currentObject)) {
                        objectsToAdd[i] = REMOVED_MARKER;
                        if (!equalityChecker.isEqual(context, entry.getValue(), entryToAdd.getValue())) {
                            if (keyDescriptor.shouldFlushMutations()) {
                                actions.add((MapAction<Map<Object, Object>>) (MapAction<?>) new MapRemoveAction<>(initialObject, initialElement));
                            }
                            actions.add((MapAction<Map<Object, Object>>) (MapAction<?>) new MapPutAction<>(entryToAdd.getKey(), entryToAdd.getValue(), initialElement));
                        }
                        continue OUTER;
                    }
                }
            }
            actions.add((MapAction<Map<Object, Object>>) (MapAction<?>) new MapRemoveAction<>(initialObject, initialElement));
        }
    }
    for (int i = 0; i < objectsToAdd.length; i++) {
        Map.Entry<Object, Object> currentObject = objectsToAdd[i];
        if (currentObject != REMOVED_MARKER) {
            Object initialElement = getViewElement(context, elementDescriptor, initial.get(currentObject.getKey()));
            actions.add((MapAction<Map<Object, Object>>) (MapAction<?>) new MapPutAction<>(currentObject.getKey(), currentObject.getValue(), initialElement));
        }
    }
    return actions;
}
Also used : MapPutAction(com.blazebit.persistence.view.impl.collection.MapPutAction) MapAction(com.blazebit.persistence.view.impl.collection.MapAction) ArrayList(java.util.ArrayList) MapRemoveAction(com.blazebit.persistence.view.impl.collection.MapRemoveAction) InitialValueAttributeAccessor(com.blazebit.persistence.view.impl.accessor.InitialValueAttributeAccessor) AttributeAccessor(com.blazebit.persistence.view.impl.accessor.AttributeAccessor) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) AbstractMap(java.util.AbstractMap) RecordingMap(com.blazebit.persistence.view.impl.collection.RecordingMap)

Example 3 with MapAction

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

the class MapAttributeFlusher method flushQuery.

@Override
public Query flushQuery(UpdateContext context, String parameterPrefix, UpdateQueryFactory queryFactory, Query query, Object ownerView, Object view, V current, UnmappedOwnerAwareDeleter ownerAwareDeleter, DirtyAttributeFlusher<?, ?, ?> ownerFlusher) {
    if (!supportsQueryFlush()) {
        throw new UnsupportedOperationException("Query flush not supported for configuration!");
    }
    if (flushOperation != null) {
        if (current instanceof RecordingMap<?, ?, ?>) {
            ((RecordingMap<?, ?, ?>) current).resetActions(context);
        } else {
            List<MapAction<Map<?, ?>>> actions = new ArrayList<>();
            actions.add(new MapClearAction());
            if (current != null && !current.isEmpty()) {
                actions.add(new MapPutAllAction(current, Collections.emptyMap()));
            }
            current = replaceWithRecordingCollection(context, view, current, actions);
        }
        invokeFlushOperation(context, ownerView, view, null, current);
    } else {
        boolean isRecording = current instanceof RecordingMap<?, ?, ?>;
        if (isRecording) {
            RecordingMap<Map<?, ?>, ?, ?> recordingMap = (RecordingMap<Map<?, ?>, ?, ?>) current;
            if (entityAttributeAccessor == null) {
                // We have a correlation mapping here
                recordingMap.resetActions(context);
            }
            Map<Object, Object> embeddables = null;
            if (elementDescriptor.shouldFlushMutations()) {
                if (elementDescriptor.shouldJpaPersistOrMerge()) {
                    mergeAndRequeue(context, recordingMap, (Map<Object, Object>) recordingMap.getDelegate());
                } else if (elementDescriptor.isSubview() && (elementDescriptor.isIdentifiable() || isIndexed())) {
                    embeddables = flushCollectionViewElements(context, current);
                }
            }
            if (entityAttributeAccessor != null && collectionUpdatable) {
                V initial = (V) viewAttributeAccessor.getInitialValue(view);
                if (initial instanceof RecordingMap<?, ?, ?>) {
                    initial = (V) ((RecordingMap) initial).getInitialVersion();
                }
                recordingMap.resetActions(context);
                // If the initial object was null like it happens during full flushing, we can only replace the collection
                flushCollectionOperations(context, ownerView, view, initial, current, embeddables, (FusedMapActions) null, initial != null);
            }
        } else {
            EqualityChecker equalityChecker;
            if (elementDescriptor.isSubview()) {
                equalityChecker = EqualsEqualityChecker.INSTANCE;
            } else {
                equalityChecker = new IdentityEqualityChecker(elementDescriptor.getBasicUserType());
            }
            V initial = (V) viewAttributeAccessor.getInitialValue(view);
            if (initial instanceof RecordingMap<?, ?, ?>) {
                initial = (V) ((RecordingMap) initial).getInitialVersion();
            }
            List<MapAction<Map<Object, Object>>> actions;
            if (initial == null && replaceWithReferenceContents || !elementDescriptor.supportsDeepEqualityCheck() || elementDescriptor.getBasicUserType() != null && !elementDescriptor.getBasicUserType().supportsDeepCloning()) {
                actions = replaceActions(current);
            } else {
                actions = determineCollectionActions(context, initial, current, equalityChecker);
            }
            current = replaceWithRecordingCollection(context, view, current, actions);
            Map<Object, Object> embeddables = null;
            if (elementDescriptor.shouldFlushMutations()) {
                if (elementDescriptor.shouldJpaPersistOrMerge()) {
                    mergeAndRequeue(context, null, (Map<Object, Object>) current);
                } else if (elementDescriptor.isSubview() && (elementDescriptor.isIdentifiable() || isIndexed())) {
                    embeddables = flushCollectionViewElements(context, current);
                }
            }
            if (entityAttributeAccessor != null && collectionUpdatable) {
                // If the initial object was null like it happens during full flushing, we can only replace the collection
                flushCollectionOperations(context, ownerView, view, initial, current, embeddables, (FusedMapActions) null, initial != null);
            }
        }
    }
    return query;
}
Also used : MapPutAllAction(com.blazebit.persistence.view.impl.collection.MapPutAllAction) MapAction(com.blazebit.persistence.view.impl.collection.MapAction) ArrayList(java.util.ArrayList) MapClearAction(com.blazebit.persistence.view.impl.collection.MapClearAction) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) AbstractMap(java.util.AbstractMap) RecordingMap(com.blazebit.persistence.view.impl.collection.RecordingMap) RecordingMap(com.blazebit.persistence.view.impl.collection.RecordingMap)

Example 4 with MapAction

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

the class MapAttributeFlusher method replaceActions.

protected List<MapAction<Map<Object, Object>>> replaceActions(V value) {
    List<MapAction<Map<Object, Object>>> actions = new ArrayList<>();
    actions.add(new MapClearAction());
    if (value != null && !value.isEmpty()) {
        actions.add(new MapPutAllAction(value, Collections.emptyMap()));
    }
    return actions;
}
Also used : MapClearAction(com.blazebit.persistence.view.impl.collection.MapClearAction) MapPutAllAction(com.blazebit.persistence.view.impl.collection.MapPutAllAction) MapAction(com.blazebit.persistence.view.impl.collection.MapAction) ArrayList(java.util.ArrayList)

Example 5 with MapAction

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

the class MapAttributeFlusher method determineCollectionActions.

protected List<MapAction<Map<Object, Object>>> determineCollectionActions(UpdateContext context, V initial, V current, EqualityChecker equalityChecker) {
    List<MapAction<Map<Object, Object>>> actions = new ArrayList<>();
    Map.Entry<Object, Object>[] objectsToAdd = (Map.Entry<Object, Object>[]) current.entrySet().toArray(new Map.Entry[current.size()]);
    if (initial != null && !initial.isEmpty()) {
        if (keyDescriptor.isSubview() && keyDescriptor.isIdentifiable()) {
            final AttributeAccessor subviewIdAccessor = keyDescriptor.getViewToEntityMapper().getViewIdAccessor();
            OUTER: for (Map.Entry<?, ?> entry : initial.entrySet()) {
                Object initialObject = entry.getKey();
                Object initialViewId = subviewIdAccessor.getValue(initialObject);
                for (int i = 0; i < objectsToAdd.length; i++) {
                    Map.Entry<Object, Object> entryToAdd = objectsToAdd[i];
                    Object currentObject = entryToAdd.getKey();
                    if (currentObject != REMOVED_MARKER) {
                        Object currentViewId = subviewIdAccessor.getValue(currentObject);
                        if (initialViewId.equals(currentViewId)) {
                            objectsToAdd[i] = REMOVED_MARKER;
                            if (!equalityChecker.isEqual(context, entry.getValue(), entryToAdd.getValue())) {
                                if (keyDescriptor.shouldFlushMutations()) {
                                    actions.add((MapAction<Map<Object, Object>>) (MapAction<?>) new MapRemoveAction<>(initialObject, (Map<Object, Object>) initial));
                                }
                                actions.add((MapAction<Map<Object, Object>>) (MapAction<?>) new MapPutAction<>(entryToAdd.getKey(), entryToAdd.getValue(), (Map<Object, Object>) initial));
                            }
                            continue OUTER;
                        }
                    }
                }
                actions.add((MapAction<Map<Object, Object>>) (MapAction<?>) new MapRemoveAction<>(initialObject, (Map<Object, Object>) initial));
            }
        } else {
            final BasicUserType<Object> basicUserType = keyDescriptor.getBasicUserType();
            OUTER: for (Map.Entry<?, ?> entry : initial.entrySet()) {
                Object initialObject = entry.getKey();
                for (int i = 0; i < objectsToAdd.length; i++) {
                    Map.Entry<Object, Object> entryToAdd = objectsToAdd[i];
                    Object currentObject = entryToAdd.getKey();
                    if (currentObject != REMOVED_MARKER) {
                        if (basicUserType.isEqual(initialObject, currentObject)) {
                            objectsToAdd[i] = REMOVED_MARKER;
                            if (!equalityChecker.isEqual(context, entry.getValue(), entryToAdd.getValue())) {
                                if (keyDescriptor.shouldFlushMutations()) {
                                    actions.add((MapAction<Map<Object, Object>>) (MapAction<?>) new MapRemoveAction<>(initialObject, (Map<Object, Object>) initial));
                                }
                                actions.add((MapAction<Map<Object, Object>>) (MapAction<?>) new MapPutAction<>(entryToAdd.getKey(), entryToAdd.getValue(), (Map<Object, Object>) initial));
                            }
                            continue OUTER;
                        }
                    }
                }
                actions.add((MapAction<Map<Object, Object>>) (MapAction<?>) new MapRemoveAction<>(initialObject, (Map<Object, Object>) initial));
            }
        }
    }
    for (int i = 0; i < objectsToAdd.length; i++) {
        Map.Entry<Object, Object> currentObject = objectsToAdd[i];
        if (currentObject != REMOVED_MARKER) {
            actions.add((MapAction<Map<Object, Object>>) (MapAction<?>) new MapPutAction<>(currentObject.getKey(), currentObject.getValue(), (Map<Object, Object>) initial));
        }
    }
    return actions;
}
Also used : MapPutAction(com.blazebit.persistence.view.impl.collection.MapPutAction) MapAction(com.blazebit.persistence.view.impl.collection.MapAction) ArrayList(java.util.ArrayList) MapRemoveAction(com.blazebit.persistence.view.impl.collection.MapRemoveAction) InitialValueAttributeAccessor(com.blazebit.persistence.view.impl.accessor.InitialValueAttributeAccessor) AttributeAccessor(com.blazebit.persistence.view.impl.accessor.AttributeAccessor) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) AbstractMap(java.util.AbstractMap) RecordingMap(com.blazebit.persistence.view.impl.collection.RecordingMap)

Aggregations

MapAction (com.blazebit.persistence.view.impl.collection.MapAction)5 ArrayList (java.util.ArrayList)5 RecordingMap (com.blazebit.persistence.view.impl.collection.RecordingMap)4 IdentityHashMap (java.util.IdentityHashMap)4 Map (java.util.Map)4 AbstractMap (java.util.AbstractMap)3 HashMap (java.util.HashMap)3 LinkedHashMap (java.util.LinkedHashMap)3 AttributeAccessor (com.blazebit.persistence.view.impl.accessor.AttributeAccessor)2 InitialValueAttributeAccessor (com.blazebit.persistence.view.impl.accessor.InitialValueAttributeAccessor)2 MapClearAction (com.blazebit.persistence.view.impl.collection.MapClearAction)2 MapPutAction (com.blazebit.persistence.view.impl.collection.MapPutAction)2 MapPutAllAction (com.blazebit.persistence.view.impl.collection.MapPutAllAction)2 MapRemoveAction (com.blazebit.persistence.view.impl.collection.MapRemoveAction)2 ViewTransition (com.blazebit.persistence.view.ViewTransition)1 CollectionAction (com.blazebit.persistence.view.impl.collection.CollectionAction)1 RecordingCollection (com.blazebit.persistence.view.impl.collection.RecordingCollection)1 SynchronizationRegistry (com.blazebit.persistence.view.impl.tx.SynchronizationRegistry)1 TransactionAccess (com.blazebit.persistence.view.spi.TransactionAccess)1 TransactionSupport (com.blazebit.persistence.view.spi.TransactionSupport)1