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);
}
}
}
}
}
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;
}
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;
}
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;
}
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;
}
Aggregations