diff options
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java')
-rw-r--r-- | plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java | 1102 |
1 files changed, 551 insertions, 551 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java index bd5b0ba57e..de4a5c3859 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java @@ -1,551 +1,551 @@ -/* - * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Eike Stepper - initial API and implementation - * Simon McDuff - bug 201266 - * Simon McDuff - bug 204890 - */ -package org.eclipse.emf.cdo.internal.common.revision.delta; - -import org.eclipse.emf.cdo.common.branch.CDOBranch; -import org.eclipse.emf.cdo.common.id.CDOID; -import org.eclipse.emf.cdo.common.id.CDOWithID; -import org.eclipse.emf.cdo.common.model.CDOModelUtil; -import org.eclipse.emf.cdo.common.protocol.CDODataInput; -import org.eclipse.emf.cdo.common.protocol.CDODataOutput; -import org.eclipse.emf.cdo.common.revision.CDOElementProxy; -import org.eclipse.emf.cdo.common.revision.CDOList; -import org.eclipse.emf.cdo.common.revision.CDORevisable; -import org.eclipse.emf.cdo.common.revision.CDORevision; -import org.eclipse.emf.cdo.common.revision.CDORevisionData; -import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; -import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor; -import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta; -import org.eclipse.emf.cdo.common.util.PartialCollectionLoadingNotSupportedException; -import org.eclipse.emf.cdo.spi.common.revision.CDOReferenceAdjuster; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDOFeatureDelta; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta; - -import org.eclipse.emf.common.util.ECollections; -import org.eclipse.emf.common.util.EList; -import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.emf.ecore.change.ListChange; -import org.eclipse.emf.ecore.change.util.ListDifferenceAnalyzer; - -import java.io.IOException; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; - -/** - * @author Eike Stepper - */ -public class CDORevisionDeltaImpl implements InternalCDORevisionDelta -{ - private EClass eClass; - - private CDOID id; - - private CDOBranch branch; - - private int version; - - private CDORevisable target; - - private Map<EStructuralFeature, CDOFeatureDelta> featureDeltas = new HashMap<EStructuralFeature, CDOFeatureDelta>(); - - public CDORevisionDeltaImpl(CDORevision revision) - { - eClass = revision.getEClass(); - id = revision.getID(); - branch = revision.getBranch(); - version = revision.getVersion(); - } - - public CDORevisionDeltaImpl(CDORevisionDelta revisionDelta, boolean copyFeatureDeltas) - { - eClass = revisionDelta.getEClass(); - id = revisionDelta.getID(); - branch = revisionDelta.getBranch(); - version = revisionDelta.getVersion(); - - if (copyFeatureDeltas) - { - for (CDOFeatureDelta delta : revisionDelta.getFeatureDeltas()) - { - addFeatureDelta(((InternalCDOFeatureDelta)delta).copy()); - } - } - } - - public CDORevisionDeltaImpl(CDORevision sourceRevision, CDORevision targetRevision) - { - if (sourceRevision.getEClass() != targetRevision.getEClass()) - { - throw new IllegalArgumentException(); - } - - eClass = sourceRevision.getEClass(); - id = sourceRevision.getID(); - branch = sourceRevision.getBranch(); - version = sourceRevision.getVersion(); - target = CDORevisionUtil.copyRevisable(targetRevision); - - compare(sourceRevision, targetRevision); - - CDORevisionData originData = sourceRevision.data(); - CDORevisionData dirtyData = targetRevision.data(); - - Object dirtyContainerID = dirtyData.getContainerID(); - if (dirtyContainerID instanceof CDOWithID) - { - dirtyContainerID = ((CDOWithID)dirtyContainerID).cdoID(); - } - - if (!compare(originData.getContainerID(), dirtyContainerID) - || !compare(originData.getContainingFeatureID(), dirtyData.getContainingFeatureID()) - || !compare(originData.getResourceID(), dirtyData.getResourceID())) - { - addFeatureDelta(new CDOContainerFeatureDeltaImpl(dirtyData.getResourceID(), dirtyContainerID, - dirtyData.getContainingFeatureID())); - } - } - - public CDORevisionDeltaImpl(CDODataInput in) throws IOException - { - eClass = (EClass)in.readCDOClassifierRefAndResolve(); - id = in.readCDOID(); - branch = in.readCDOBranch(); - version = in.readInt(); - if (version < 0) - { - version = -version; - target = in.readCDORevisable(); - } - - int size = in.readInt(); - for (int i = 0; i < size; i++) - { - CDOFeatureDelta featureDelta = in.readCDOFeatureDelta(eClass); - featureDeltas.put(featureDelta.getFeature(), featureDelta); - } - } - - public void write(CDODataOutput out) throws IOException - { - out.writeCDOClassifierRef(eClass); - out.writeCDOID(id); - out.writeCDOBranch(branch); - if (target == null) - { - out.writeInt(version); - } - else - { - out.writeInt(-version); - out.writeCDORevisable(target); - } - - out.writeInt(featureDeltas.size()); - for (CDOFeatureDelta featureDelta : featureDeltas.values()) - { - out.writeCDOFeatureDelta(eClass, featureDelta); - } - } - - public EClass getEClass() - { - return eClass; - } - - public CDOID getID() - { - return id; - } - - public CDOBranch getBranch() - { - return branch; - } - - public void setBranch(CDOBranch branch) - { - this.branch = branch; - } - - public int getVersion() - { - return version; - } - - public void setVersion(int version) - { - this.version = version; - } - - public CDORevisable getTarget() - { - return target; - } - - public void setTarget(CDORevisable target) - { - this.target = target; - } - - public boolean isEmpty() - { - return featureDeltas.isEmpty(); - } - - public CDORevisionDelta copy() - { - return new CDORevisionDeltaImpl(this, true); - } - - public Map<EStructuralFeature, CDOFeatureDelta> getFeatureDeltaMap() - { - return featureDeltas; - } - - public CDOFeatureDelta getFeatureDelta(EStructuralFeature feature) - { - return featureDeltas.get(feature); - } - - public List<CDOFeatureDelta> getFeatureDeltas() - { - return new ArrayList<CDOFeatureDelta>(featureDeltas.values()); - } - - public void apply(CDORevision revision) - { - for (CDOFeatureDelta featureDelta : featureDeltas.values()) - { - ((CDOFeatureDeltaImpl)featureDelta).apply(revision); - } - } - - public void addFeatureDelta(CDOFeatureDelta delta) - { - if (delta instanceof CDOListFeatureDelta) - { - CDOListFeatureDelta deltas = (CDOListFeatureDelta)delta; - for (CDOFeatureDelta childDelta : deltas.getListChanges()) - { - addFeatureDelta(childDelta); - } - } - else - { - addSingleFeatureDelta(delta); - } - } - - private void addSingleFeatureDelta(CDOFeatureDelta delta) - { - EStructuralFeature feature = delta.getFeature(); - if (feature.isMany()) - { - CDOListFeatureDeltaImpl listDelta = (CDOListFeatureDeltaImpl)featureDeltas.get(feature); - if (listDelta == null) - { - listDelta = new CDOListFeatureDeltaImpl(feature); - featureDeltas.put(listDelta.getFeature(), listDelta); - } - - // Remove all previous changes - if (delta instanceof CDOClearFeatureDelta || delta instanceof CDOUnsetFeatureDelta) - { - listDelta.getListChanges().clear(); - } - - listDelta.add(delta); - } - else - { - featureDeltas.put(feature, delta); - } - } - - public boolean adjustReferences(CDOReferenceAdjuster referenceAdjuster) - { - boolean changed = false; - for (CDOFeatureDelta featureDelta : featureDeltas.values()) - { - changed |= ((CDOFeatureDeltaImpl)featureDelta).adjustReferences(referenceAdjuster); - } - - return changed; - } - - public void accept(CDOFeatureDeltaVisitor visitor) - { - for (CDOFeatureDelta featureDelta : featureDeltas.values()) - { - ((CDOFeatureDeltaImpl)featureDelta).accept(visitor); - } - } - - private void compare(CDORevision originRevision, CDORevision dirtyRevision) - { - CDORevisionData originData = originRevision.data(); - CDORevisionData dirtyData = dirtyRevision.data(); - - for (final EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(eClass)) - { - if (feature.isMany()) - { - if (originData.size(feature) > 0 && dirtyData.size(feature) == 0) - { - addFeatureDelta(new CDOClearFeatureDeltaImpl(feature)); - } - else - { - CDOListFeatureDelta listFeatureDelta = new CDOListFeatureDeltaImpl(feature); - final List<CDOFeatureDelta> changes = listFeatureDelta.getListChanges(); - - ListDifferenceAnalyzer analyzer = new ListDifferenceAnalyzer() - { - @Override - public void analyzeLists(EList<Object> oldList, EList<?> newList, EList<ListChange> listChanges) - { - checkNoProxies(oldList); - checkNoProxies(newList); - super.analyzeLists(oldList, newList, listChanges); - } - - @Override - protected void createAddListChange(EList<Object> oldList, EList<ListChange> listChanges, Object value, - int index) - { - CDOFeatureDelta delta = new CDOAddFeatureDeltaImpl(feature, index, value); - changes.add(delta); - oldList.add(index, value); - } - - @Override - protected void createRemoveListChange(EList<?> oldList, EList<ListChange> listChanges, Object value, - int index) - { - CDORemoveFeatureDeltaImpl delta = new CDORemoveFeatureDeltaImpl(feature, index); - // fix until ListDifferenceAnalyzer delivers the correct value (bug #308618). - delta.setValue(oldList.get(index)); - changes.add(delta); - oldList.remove(index); - } - - @Override - protected void createMoveListChange(EList<?> oldList, EList<ListChange> listChanges, Object value, - int index, int toIndex) - { - CDOMoveFeatureDeltaImpl delta = new CDOMoveFeatureDeltaImpl(feature, toIndex, index); - // fix until ListDifferenceAnalyzer delivers the correct value (same problem as bug #308618). - delta.setValue(oldList.get(index)); - changes.add(delta); - oldList.move(toIndex, index); - } - - private void checkNoProxies(EList<?> list) - { - for (Object element : list) - { - if (element instanceof CDOElementProxy) - { - throw new PartialCollectionLoadingNotSupportedException("List contains proxy elements"); - } - } - } - }; - - CDOList originList = ((InternalCDORevision)originRevision).getList(feature); - CDOList dirtyList = ((InternalCDORevision)dirtyRevision).getList(feature); - - analyzer.analyzeLists(originList, dirtyList, new NOOPList()); - if (!changes.isEmpty()) - { - featureDeltas.put(feature, listFeatureDelta); - } - } - } - else - { - Object originValue = originData.get(feature, 0); - Object dirtyValue = dirtyData.get(feature, 0); - if (!compare(originValue, dirtyValue)) - { - if (dirtyValue == null) - { - addFeatureDelta(new CDOUnsetFeatureDeltaImpl(feature)); - } - else - { - addFeatureDelta(new CDOSetFeatureDeltaImpl(feature, 0, dirtyValue, originValue)); - } - } - } - } - } - - private boolean compare(Object originValue, Object dirtyValue) - { - return originValue == dirtyValue || originValue != null && dirtyValue != null && originValue.equals(dirtyValue); - } - - @Override - public String toString() - { - return MessageFormat.format("CDORevisionDelta[{0}@{1}:{2}v{3} --> {4}]", eClass.getName(), id, branch.getID(), - version, featureDeltas.values()); - } - - /** - * @author Eike Stepper - */ - public static class NOOPList implements EList<ListChange> - { - private static final EList<ListChange> LIST = ECollections.emptyEList(); - - public NOOPList() - { - } - - public int size() - { - return 0; - } - - public boolean isEmpty() - { - return true; - } - - public boolean contains(Object o) - { - return false; - } - - public Iterator<ListChange> iterator() - { - return LIST.iterator(); - } - - public Object[] toArray() - { - return LIST.toArray(); - } - - public <T> T[] toArray(T[] a) - { - return LIST.toArray(a); - } - - public boolean add(ListChange o) - { - return false; - } - - public boolean remove(Object o) - { - return false; - } - - public boolean containsAll(Collection<?> c) - { - return false; - } - - public boolean addAll(Collection<? extends ListChange> c) - { - return false; - } - - public boolean addAll(int index, Collection<? extends ListChange> c) - { - return false; - } - - public boolean removeAll(Collection<?> c) - { - return false; - } - - public boolean retainAll(Collection<?> c) - { - return false; - } - - public void clear() - { - } - - public ListChange get(int index) - { - return LIST.get(index); - } - - public ListChange set(int index, ListChange element) - { - return null; - } - - public void add(int index, ListChange element) - { - } - - public ListChange remove(int index) - { - return null; - } - - public int indexOf(Object o) - { - return LIST.indexOf(o); - } - - public int lastIndexOf(Object o) - { - return LIST.lastIndexOf(o); - } - - public ListIterator<ListChange> listIterator() - { - return LIST.listIterator(); - } - - public ListIterator<ListChange> listIterator(int index) - { - return LIST.listIterator(index); - } - - public List<ListChange> subList(int fromIndex, int toIndex) - { - return LIST.subList(fromIndex, toIndex); - } - - public void move(int newPosition, ListChange object) - { - } - - public ListChange move(int newPosition, int oldPosition) - { - return null; - } - } -} +/*
+ * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ * Simon McDuff - bug 201266
+ * Simon McDuff - bug 204890
+ */
+package org.eclipse.emf.cdo.internal.common.revision.delta;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOWithID;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDOElementProxy;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevisable;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionData;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
+import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
+import org.eclipse.emf.cdo.common.util.PartialCollectionLoadingNotSupportedException;
+import org.eclipse.emf.cdo.spi.common.revision.CDOReferenceAdjuster;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDOFeatureDelta;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+
+import org.eclipse.emf.common.util.ECollections;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.change.ListChange;
+import org.eclipse.emf.ecore.change.util.ListDifferenceAnalyzer;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+public class CDORevisionDeltaImpl implements InternalCDORevisionDelta
+{
+ private EClass eClass;
+
+ private CDOID id;
+
+ private CDOBranch branch;
+
+ private int version;
+
+ private CDORevisable target;
+
+ private Map<EStructuralFeature, CDOFeatureDelta> featureDeltas = new HashMap<EStructuralFeature, CDOFeatureDelta>();
+
+ public CDORevisionDeltaImpl(CDORevision revision)
+ {
+ eClass = revision.getEClass();
+ id = revision.getID();
+ branch = revision.getBranch();
+ version = revision.getVersion();
+ }
+
+ public CDORevisionDeltaImpl(CDORevisionDelta revisionDelta, boolean copyFeatureDeltas)
+ {
+ eClass = revisionDelta.getEClass();
+ id = revisionDelta.getID();
+ branch = revisionDelta.getBranch();
+ version = revisionDelta.getVersion();
+
+ if (copyFeatureDeltas)
+ {
+ for (CDOFeatureDelta delta : revisionDelta.getFeatureDeltas())
+ {
+ addFeatureDelta(((InternalCDOFeatureDelta)delta).copy());
+ }
+ }
+ }
+
+ public CDORevisionDeltaImpl(CDORevision sourceRevision, CDORevision targetRevision)
+ {
+ if (sourceRevision.getEClass() != targetRevision.getEClass())
+ {
+ throw new IllegalArgumentException();
+ }
+
+ eClass = sourceRevision.getEClass();
+ id = sourceRevision.getID();
+ branch = sourceRevision.getBranch();
+ version = sourceRevision.getVersion();
+ target = CDORevisionUtil.copyRevisable(targetRevision);
+
+ compare(sourceRevision, targetRevision);
+
+ CDORevisionData originData = sourceRevision.data();
+ CDORevisionData dirtyData = targetRevision.data();
+
+ Object dirtyContainerID = dirtyData.getContainerID();
+ if (dirtyContainerID instanceof CDOWithID)
+ {
+ dirtyContainerID = ((CDOWithID)dirtyContainerID).cdoID();
+ }
+
+ if (!compare(originData.getContainerID(), dirtyContainerID)
+ || !compare(originData.getContainingFeatureID(), dirtyData.getContainingFeatureID())
+ || !compare(originData.getResourceID(), dirtyData.getResourceID()))
+ {
+ addFeatureDelta(new CDOContainerFeatureDeltaImpl(dirtyData.getResourceID(), dirtyContainerID,
+ dirtyData.getContainingFeatureID()));
+ }
+ }
+
+ public CDORevisionDeltaImpl(CDODataInput in) throws IOException
+ {
+ eClass = (EClass)in.readCDOClassifierRefAndResolve();
+ id = in.readCDOID();
+ branch = in.readCDOBranch();
+ version = in.readInt();
+ if (version < 0)
+ {
+ version = -version;
+ target = in.readCDORevisable();
+ }
+
+ int size = in.readInt();
+ for (int i = 0; i < size; i++)
+ {
+ CDOFeatureDelta featureDelta = in.readCDOFeatureDelta(eClass);
+ featureDeltas.put(featureDelta.getFeature(), featureDelta);
+ }
+ }
+
+ public void write(CDODataOutput out) throws IOException
+ {
+ out.writeCDOClassifierRef(eClass);
+ out.writeCDOID(id);
+ out.writeCDOBranch(branch);
+ if (target == null)
+ {
+ out.writeInt(version);
+ }
+ else
+ {
+ out.writeInt(-version);
+ out.writeCDORevisable(target);
+ }
+
+ out.writeInt(featureDeltas.size());
+ for (CDOFeatureDelta featureDelta : featureDeltas.values())
+ {
+ out.writeCDOFeatureDelta(eClass, featureDelta);
+ }
+ }
+
+ public EClass getEClass()
+ {
+ return eClass;
+ }
+
+ public CDOID getID()
+ {
+ return id;
+ }
+
+ public CDOBranch getBranch()
+ {
+ return branch;
+ }
+
+ public void setBranch(CDOBranch branch)
+ {
+ this.branch = branch;
+ }
+
+ public int getVersion()
+ {
+ return version;
+ }
+
+ public void setVersion(int version)
+ {
+ this.version = version;
+ }
+
+ public CDORevisable getTarget()
+ {
+ return target;
+ }
+
+ public void setTarget(CDORevisable target)
+ {
+ this.target = target;
+ }
+
+ public boolean isEmpty()
+ {
+ return featureDeltas.isEmpty();
+ }
+
+ public CDORevisionDelta copy()
+ {
+ return new CDORevisionDeltaImpl(this, true);
+ }
+
+ public Map<EStructuralFeature, CDOFeatureDelta> getFeatureDeltaMap()
+ {
+ return featureDeltas;
+ }
+
+ public CDOFeatureDelta getFeatureDelta(EStructuralFeature feature)
+ {
+ return featureDeltas.get(feature);
+ }
+
+ public List<CDOFeatureDelta> getFeatureDeltas()
+ {
+ return new ArrayList<CDOFeatureDelta>(featureDeltas.values());
+ }
+
+ public void apply(CDORevision revision)
+ {
+ for (CDOFeatureDelta featureDelta : featureDeltas.values())
+ {
+ ((CDOFeatureDeltaImpl)featureDelta).apply(revision);
+ }
+ }
+
+ public void addFeatureDelta(CDOFeatureDelta delta)
+ {
+ if (delta instanceof CDOListFeatureDelta)
+ {
+ CDOListFeatureDelta deltas = (CDOListFeatureDelta)delta;
+ for (CDOFeatureDelta childDelta : deltas.getListChanges())
+ {
+ addFeatureDelta(childDelta);
+ }
+ }
+ else
+ {
+ addSingleFeatureDelta(delta);
+ }
+ }
+
+ private void addSingleFeatureDelta(CDOFeatureDelta delta)
+ {
+ EStructuralFeature feature = delta.getFeature();
+ if (feature.isMany())
+ {
+ CDOListFeatureDeltaImpl listDelta = (CDOListFeatureDeltaImpl)featureDeltas.get(feature);
+ if (listDelta == null)
+ {
+ listDelta = new CDOListFeatureDeltaImpl(feature);
+ featureDeltas.put(listDelta.getFeature(), listDelta);
+ }
+
+ // Remove all previous changes
+ if (delta instanceof CDOClearFeatureDelta || delta instanceof CDOUnsetFeatureDelta)
+ {
+ listDelta.getListChanges().clear();
+ }
+
+ listDelta.add(delta);
+ }
+ else
+ {
+ featureDeltas.put(feature, delta);
+ }
+ }
+
+ public boolean adjustReferences(CDOReferenceAdjuster referenceAdjuster)
+ {
+ boolean changed = false;
+ for (CDOFeatureDelta featureDelta : featureDeltas.values())
+ {
+ changed |= ((CDOFeatureDeltaImpl)featureDelta).adjustReferences(referenceAdjuster);
+ }
+
+ return changed;
+ }
+
+ public void accept(CDOFeatureDeltaVisitor visitor)
+ {
+ for (CDOFeatureDelta featureDelta : featureDeltas.values())
+ {
+ ((CDOFeatureDeltaImpl)featureDelta).accept(visitor);
+ }
+ }
+
+ private void compare(CDORevision originRevision, CDORevision dirtyRevision)
+ {
+ CDORevisionData originData = originRevision.data();
+ CDORevisionData dirtyData = dirtyRevision.data();
+
+ for (final EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(eClass))
+ {
+ if (feature.isMany())
+ {
+ if (originData.size(feature) > 0 && dirtyData.size(feature) == 0)
+ {
+ addFeatureDelta(new CDOClearFeatureDeltaImpl(feature));
+ }
+ else
+ {
+ CDOListFeatureDelta listFeatureDelta = new CDOListFeatureDeltaImpl(feature);
+ final List<CDOFeatureDelta> changes = listFeatureDelta.getListChanges();
+
+ ListDifferenceAnalyzer analyzer = new ListDifferenceAnalyzer()
+ {
+ @Override
+ public void analyzeLists(EList<Object> oldList, EList<?> newList, EList<ListChange> listChanges)
+ {
+ checkNoProxies(oldList);
+ checkNoProxies(newList);
+ super.analyzeLists(oldList, newList, listChanges);
+ }
+
+ @Override
+ protected void createAddListChange(EList<Object> oldList, EList<ListChange> listChanges, Object value,
+ int index)
+ {
+ CDOFeatureDelta delta = new CDOAddFeatureDeltaImpl(feature, index, value);
+ changes.add(delta);
+ oldList.add(index, value);
+ }
+
+ @Override
+ protected void createRemoveListChange(EList<?> oldList, EList<ListChange> listChanges, Object value,
+ int index)
+ {
+ CDORemoveFeatureDeltaImpl delta = new CDORemoveFeatureDeltaImpl(feature, index);
+ // fix until ListDifferenceAnalyzer delivers the correct value (bug #308618).
+ delta.setValue(oldList.get(index));
+ changes.add(delta);
+ oldList.remove(index);
+ }
+
+ @Override
+ protected void createMoveListChange(EList<?> oldList, EList<ListChange> listChanges, Object value,
+ int index, int toIndex)
+ {
+ CDOMoveFeatureDeltaImpl delta = new CDOMoveFeatureDeltaImpl(feature, toIndex, index);
+ // fix until ListDifferenceAnalyzer delivers the correct value (same problem as bug #308618).
+ delta.setValue(oldList.get(index));
+ changes.add(delta);
+ oldList.move(toIndex, index);
+ }
+
+ private void checkNoProxies(EList<?> list)
+ {
+ for (Object element : list)
+ {
+ if (element instanceof CDOElementProxy)
+ {
+ throw new PartialCollectionLoadingNotSupportedException("List contains proxy elements");
+ }
+ }
+ }
+ };
+
+ CDOList originList = ((InternalCDORevision)originRevision).getList(feature);
+ CDOList dirtyList = ((InternalCDORevision)dirtyRevision).getList(feature);
+
+ analyzer.analyzeLists(originList, dirtyList, new NOOPList());
+ if (!changes.isEmpty())
+ {
+ featureDeltas.put(feature, listFeatureDelta);
+ }
+ }
+ }
+ else
+ {
+ Object originValue = originData.get(feature, 0);
+ Object dirtyValue = dirtyData.get(feature, 0);
+ if (!compare(originValue, dirtyValue))
+ {
+ if (dirtyValue == null)
+ {
+ addFeatureDelta(new CDOUnsetFeatureDeltaImpl(feature));
+ }
+ else
+ {
+ addFeatureDelta(new CDOSetFeatureDeltaImpl(feature, 0, dirtyValue, originValue));
+ }
+ }
+ }
+ }
+ }
+
+ private boolean compare(Object originValue, Object dirtyValue)
+ {
+ return originValue == dirtyValue || originValue != null && dirtyValue != null && originValue.equals(dirtyValue);
+ }
+
+ @Override
+ public String toString()
+ {
+ return MessageFormat.format("CDORevisionDelta[{0}@{1}:{2}v{3} --> {4}]", eClass.getName(), id, branch.getID(),
+ version, featureDeltas.values());
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static class NOOPList implements EList<ListChange>
+ {
+ private static final EList<ListChange> LIST = ECollections.emptyEList();
+
+ public NOOPList()
+ {
+ }
+
+ public int size()
+ {
+ return 0;
+ }
+
+ public boolean isEmpty()
+ {
+ return true;
+ }
+
+ public boolean contains(Object o)
+ {
+ return false;
+ }
+
+ public Iterator<ListChange> iterator()
+ {
+ return LIST.iterator();
+ }
+
+ public Object[] toArray()
+ {
+ return LIST.toArray();
+ }
+
+ public <T> T[] toArray(T[] a)
+ {
+ return LIST.toArray(a);
+ }
+
+ public boolean add(ListChange o)
+ {
+ return false;
+ }
+
+ public boolean remove(Object o)
+ {
+ return false;
+ }
+
+ public boolean containsAll(Collection<?> c)
+ {
+ return false;
+ }
+
+ public boolean addAll(Collection<? extends ListChange> c)
+ {
+ return false;
+ }
+
+ public boolean addAll(int index, Collection<? extends ListChange> c)
+ {
+ return false;
+ }
+
+ public boolean removeAll(Collection<?> c)
+ {
+ return false;
+ }
+
+ public boolean retainAll(Collection<?> c)
+ {
+ return false;
+ }
+
+ public void clear()
+ {
+ }
+
+ public ListChange get(int index)
+ {
+ return LIST.get(index);
+ }
+
+ public ListChange set(int index, ListChange element)
+ {
+ return null;
+ }
+
+ public void add(int index, ListChange element)
+ {
+ }
+
+ public ListChange remove(int index)
+ {
+ return null;
+ }
+
+ public int indexOf(Object o)
+ {
+ return LIST.indexOf(o);
+ }
+
+ public int lastIndexOf(Object o)
+ {
+ return LIST.lastIndexOf(o);
+ }
+
+ public ListIterator<ListChange> listIterator()
+ {
+ return LIST.listIterator();
+ }
+
+ public ListIterator<ListChange> listIterator(int index)
+ {
+ return LIST.listIterator(index);
+ }
+
+ public List<ListChange> subList(int fromIndex, int toIndex)
+ {
+ return LIST.subList(fromIndex, toIndex);
+ }
+
+ public void move(int newPosition, ListChange object)
+ {
+ }
+
+ public ListChange move(int newPosition, int oldPosition)
+ {
+ return null;
+ }
+ }
+}
|