private void pickChangesIntoResult( Side side, EStructuralFeature feature, BasicEList<Element> ancestorList, PerSide<List<CDOFeatureDelta>> changesPerSide, Map<CDOFeatureDelta, Element> allElements, Map<Object, List<Element>> additions, List<CDOFeatureDelta> result) { List<CDOFeatureDelta> changes = changesPerSide.get(side); for (CDOFeatureDelta change : changes) { Type changeType = change.getType(); switch (changeType) { case ADD: { CDOAddFeatureDeltaImpl addChange = (CDOAddFeatureDeltaImpl) change; result.add(addChange); int sideIndex = addChange.getIndex(); int ancestorIndex = sideIndex; int ancestorEnd = ancestorList.size(); if (ancestorIndex > ancestorEnd) { // TODO Better way to adjust ancestor indexes? ancestorIndex = ancestorEnd; addChange.setIndex(ancestorIndex); } Element newElement = allElements.get(addChange); ancestorList.add(ancestorIndex, newElement); if (treatAsUnique(feature)) { // Detect and remove corresponding AddDeltas from the other side Object value = addChange.getValue(); List<Element> elementsToAdd = additions.get(value); if (elementsToAdd != null) { for (Element element : elementsToAdd) { CDOAddFeatureDelta otherAdd = (CDOAddFeatureDelta) element.get(other(side)); if (otherAdd != null) { element.set(other(side), null); // Not taking an AddDelta has the same effect on indexes as a removal of the // element List<CDOFeatureDelta> otherChanges = changesPerSide.get(other(side)); int otherIndex = otherAdd.getIndex(); adjustAfterRemoval(otherChanges, otherIndex, addChange); } } } } break; } case REMOVE: { CDORemoveFeatureDeltaImpl removeChange = (CDORemoveFeatureDeltaImpl) change; result.add(removeChange); Element removedElement = allElements.get(removeChange); int ancestorIndex = ancestorList.indexOf(removedElement); removeChange.setIndex(ancestorIndex); ancestorList.remove(ancestorIndex); // Detect and remove a potential duplicate RemoveDelta from the other side CDOFeatureDelta otherChange = removedElement.get(other(side)); if (otherChange != null) { Type otherChangeType = otherChange.getType(); switch (otherChangeType) { case REMOVE: { CDORemoveFeatureDelta otherRemove = (CDORemoveFeatureDelta) otherChange; removedElement.set(other(side), null); // Not taking a RemoveDelta has the same effect on indexes as an addition of // the element List<CDOFeatureDelta> otherChanges = changesPerSide.get(other(side)); int otherIndex = otherRemove.getIndex(); adjustAfterAddition(otherChanges, otherIndex, otherRemove); break; } case MOVE: { CDOMoveFeatureDelta otherMove = (CDOMoveFeatureDelta) otherChange; removedElement.set(other(side), null); // Not taking a MoveDelta has the same effect on indexes as a reverse move // of the element List<CDOFeatureDelta> otherChanges = changesPerSide.get(other(side)); int otherOldPosition = otherMove.getOldPosition(); int otherNewPosition = otherMove.getNewPosition(); adjustAfterMove( otherChanges, otherOldPosition, otherNewPosition, otherMove); break; } default: throw new IllegalStateException("Unexpected change type: " + otherChangeType); } } break; } case SET: { throw new IllegalStateException("Unhandled change type: " + changeType); // CDOSetFeatureDelta setChange = (CDOSetFeatureDelta)change; // break; } case MOVE: { CDOMoveFeatureDeltaImpl moveChange = (CDOMoveFeatureDeltaImpl) change; int sideOldPosition = moveChange.getOldPosition(); int sideNewPosition = moveChange.getNewPosition(); Element movedElement = allElements.get(moveChange); CDOFeatureDelta otherChange = movedElement.get(other(side)); if (otherChange != null) { Type otherChangeType = otherChange.getType(); switch (otherChangeType) { case REMOVE: { // Prioritize the RemoveDelta of the other side, delete the MoveDelta from // this side adjustAfterMove(changes, sideOldPosition, sideNewPosition, moveChange); movedElement.set(side, null); return; } case MOVE: { CDOMoveFeatureDelta otherMove = (CDOMoveFeatureDelta) otherChange; movedElement.set(other(side), null); // Not taking a MoveDelta has the same effect on indexes as a reverse move // of the element List<CDOFeatureDelta> otherChanges = changesPerSide.get(other(side)); int otherOldPosition = otherMove.getOldPosition(); int otherNewPosition = otherMove.getNewPosition(); adjustAfterMove( otherChanges, otherOldPosition, otherNewPosition, otherMove); movedElement.set(other(side), null); break; } default: throw new IllegalStateException("Unexpected change type: " + otherChangeType); } } int positionDelta = sideNewPosition - sideOldPosition; int ancestorOldPosition = ancestorList.indexOf(movedElement); int ancestorNewPosition = ancestorOldPosition + positionDelta; if (ancestorNewPosition < 0) { ancestorNewPosition = 0; } int ancestorEnd = ancestorList.size() - 1; if (ancestorNewPosition > ancestorEnd) { ancestorNewPosition = ancestorEnd; } moveChange.setOldPosition(ancestorOldPosition); moveChange.setNewPosition(ancestorNewPosition); result.add(moveChange); ancestorList.move(ancestorNewPosition, ancestorOldPosition); break; } case CLEAR: case UNSET: default: throw new IllegalStateException("Illegal change type: " + changeType); } } }
private void applyChangesToWorkList( Side side, PerSide<BasicEList<Element>> listPerSide, PerSide<List<CDOFeatureDelta>> changesPerSide, Map<CDOFeatureDelta, Element> allElements, Map<Object, List<Element>> additions) { BasicEList<Element> list = listPerSide.get(side); List<CDOFeatureDelta> changes = changesPerSide.get(side); for (CDOFeatureDelta change : changes) { Type changeType = change.getType(); switch (changeType) { case ADD: { CDOAddFeatureDelta addChange = (CDOAddFeatureDelta) change; Element element = new Element(-1); element.set(side, addChange); allElements.put(addChange, element); list.add(addChange.getIndex(), element); rememberAddition(addChange.getValue(), element, additions); break; } case REMOVE: { CDORemoveFeatureDelta removeChange = (CDORemoveFeatureDelta) change; Element element = list.remove(removeChange.getIndex()); element.set(side, removeChange); allElements.put(removeChange, element); break; } case SET: { CDOSetFeatureDelta setChange = (CDOSetFeatureDelta) change; Element newElement = new Element(-1); newElement.set(side, setChange); rememberAddition(setChange.getValue(), newElement, additions); Element oldElement = list.set(setChange.getIndex(), newElement); oldElement.set(side, setChange); allElements.put(setChange, oldElement); break; } case MOVE: { CDOMoveFeatureDelta moveChange = (CDOMoveFeatureDelta) change; Element element = list.move(moveChange.getNewPosition(), moveChange.getOldPosition()); element.set(side, moveChange); allElements.put(moveChange, element); break; } case CLEAR: case UNSET: // These deltas should have been replaced by multiple REMOVE deltas in // copyListChanges() throw new IllegalStateException("Unhandled change type: " + changeType); default: throw new IllegalStateException("Illegal change type: " + changeType); } } }