Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCedric Notot2013-06-07 05:40:20 -0400
committerLaurent Goubet2013-06-21 07:04:50 -0400
commit4a8ef93f5473bca8faa7dadd6dc6a123542ce0c6 (patch)
tree6c8b7d46ef18389ed5041652b7b39ec6cbae72b5
parent099f3f702c577f1ee81b66680a2f81c548e5f031 (diff)
downloadorg.eclipse.emf.compare-4a8ef93f5473bca8faa7dadd6dc6a123542ce0c6.tar.gz
org.eclipse.emf.compare-4a8ef93f5473bca8faa7dadd6dc6a123542ce0c6.tar.xz
org.eclipse.emf.compare-4a8ef93f5473bca8faa7dadd6dc6a123542ce0c6.zip
Filling of the implication link with UML subsets.
Like equivalences, the merge of a difference may imply the merge of other ones. But, contrary to equivalences, this implication link is unidirectional. So, if A implies B, B does not imply A. In the context of UML, references can be defined as subset of other ones. So, the merge of the add of a reference which is subset of another one implies the add of this last one. In the same way, the delete of a reference which is superset of other ones implies the delete of these last ones. Note that some superset references can be defined as 'union' (that is to say that each superset reference is in one of the subsets). Union supersets are derived, so they are not managed by EMF Compare. The implications are set in Diff#implies and Diff#impliedBy. The reference merger of EMF Compare scans these links to mark as merged the impacted differences without merging them (because the merge itself will be managed by the 'meta-model'). Change-Id: If3a62076c3569b1ba0aa4628c657765cd8ad7711
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/DiagramContentMergeViewer.java2
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/AbstractTest.java24
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/EdgeMergeTest.java112
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/NodeMergeTest.java8
-rw-r--r--plugins/org.eclipse.emf.compare.edit/plugin.properties2
-rw-r--r--plugins/org.eclipse.emf.compare.edit/src-gen/org/eclipse/emf/compare/provider/DiffItemProvider.java32
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/table/TableContentMergeViewer.java4
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/tree/TreeContentMergeViewer.java6
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/contentmergeviewer/accessor/impl/ManyStructuralFeatureAccessorImpl.java2
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/MergeViewerItem.java2
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/ResourceAttachmentChangeMergeViewerItem.java2
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/diff/ComparisonUtilTest.java120
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/diff/DiffUtilTest.java101
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/suite/AllTests.java11
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.rcp.ui/src/org/eclipse/emf/compare/uml2/rcp/ui/internal/accessor/UMLStereotypeApplicationChangeFeatureAccessor.java2
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/AbstractTest.java26
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociation2Test.java35
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociation3Test.java23
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociationTest.java127
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/ChangeAssociationTest.java16
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/dependency/AddInterfaceRealizationTest.java24
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/dependency/AddSubstitutionTest.java26
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsAssociationTest.java1036
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsInterfaceRealizationTest.java962
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsTransitionTest.java901
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/ImplicationsInputData.java41
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a1/left.uml15
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a1/right.uml5
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a2/left.uml14
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a2/right.uml9
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a3/left.uml8
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a3/right.uml5
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/suite/AllTests.java6
-rw-r--r--plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/UMLPostProcessor.java245
-rw-r--r--plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/util/UMLCompareUtil.java100
-rw-r--r--plugins/org.eclipse.emf.compare/META-INF/MANIFEST.MF5
-rw-r--r--plugins/org.eclipse.emf.compare/model/compare.ecore790
-rw-r--r--plugins/org.eclipse.emf.compare/model/compare.genmodel220
-rw-r--r--plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/ComparePackage.java126
-rw-r--r--plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/Diff.java44
-rw-r--r--plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/impl/ComparePackageImpl.java44
-rw-r--r--plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/impl/DiffImpl.java80
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/conflict/DefaultConflictDetector.java60
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/diff/DefaultDiffEngine.java2
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/ComparisonUtil.java270
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/DiffUtil.java1057
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/eobject/EditionDistance.java2
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/resource/NameSimilarityMatchingStrategy.java2
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AttributeChangeMerger.java2
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ReferenceChangeMerger.java359
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ResourceAttachmentChangeMerger.java2
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/req/DefaultReqEngine.java74
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/DiffUtil.java967
53 files changed, 5894 insertions, 2266 deletions
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/DiagramContentMergeViewer.java b/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/DiagramContentMergeViewer.java
index b8034848c..90a86939c 100644
--- a/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/DiagramContentMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui/src/org/eclipse/emf/compare/diagram/ide/ui/internal/contentmergeviewer/diagram/DiagramContentMergeViewer.java
@@ -61,10 +61,10 @@ import org.eclipse.emf.compare.diagram.internal.extensions.Show;
import org.eclipse.emf.compare.diagram.internal.factories.extensions.CoordinatesChangeFactory;
import org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer;
import org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.tree.TreeContentMergeViewerContentProvider;
+import org.eclipse.emf.compare.internal.utils.DiffUtil;
import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.IMergeViewer;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.IMergeViewer.MergeViewerSide;
-import org.eclipse.emf.compare.utils.DiffUtil;
import org.eclipse.emf.compare.utils.ReferenceUtil;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.ConnectionEditPart;
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/AbstractTest.java b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/AbstractTest.java
index 52883ffa9..591ed5faf 100644
--- a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/AbstractTest.java
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/AbstractTest.java
@@ -13,12 +13,14 @@ package org.eclipse.emf.compare.diagram.papyrus.tests;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.DifferenceKind;
import org.eclipse.emf.compare.EMFCompare;
import org.eclipse.emf.compare.ReferenceChange;
import org.eclipse.emf.compare.diagram.internal.CompareDiagramPostProcessor;
@@ -32,6 +34,7 @@ import org.eclipse.emf.compare.tests.postprocess.data.TestPostProcessor;
import org.eclipse.emf.compare.uml2.internal.UMLDiff;
import org.eclipse.emf.compare.uml2.internal.merge.UMLMerger;
import org.eclipse.emf.compare.uml2.internal.postprocessor.UMLPostProcessor;
+import org.eclipse.emf.compare.utils.EMFComparePredicates;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
@@ -42,6 +45,7 @@ import org.junit.After;
import org.junit.Before;
import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
@@ -147,8 +151,26 @@ public abstract class AbstractTest {
}
testIntersections(comparison);
}
+
+ // FIXME: See Bug 410737
+ protected void diffsCheckingBug410737(Comparison comparison, int totalDiffsNb, ExpectedStat ... expectedStats) {
+ List<Diff> diffs = comparison.getDifferences();
+ Collection<Diff> differences = Collections2.filter(diffs, Predicates.not(EMFComparePredicates.ofKind(DifferenceKind.MOVE)));
+
+ assertEquals(totalDiffsNb, differences.size());
+ for (ExpectedStat expectedStat : expectedStats) {
+ Predicate<Diff> p = expectedStat.p;
+ int nb = expectedStat.nb;
+ int result = Collections2.filter(differences, p).size();
+
+ String message = buildAssertMessage(differences, p);
+
+ assertEquals(message, nb, result);
+ }
+ testIntersections(comparison);
+ }
- private String buildAssertMessage(List<Diff> differences, Predicate<Diff> p) {
+ private String buildAssertMessage(Collection<Diff> differences, Predicate<Diff> p) {
Diff diff = Iterables.find(differences, p, null);
String message = "";
if (diff != null) {
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/EdgeMergeTest.java b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/EdgeMergeTest.java
index d288becf9..f37b64b0a 100644
--- a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/EdgeMergeTest.java
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/EdgeMergeTest.java
@@ -44,12 +44,12 @@ public class EdgeMergeTest extends AbstractTest {
private EdgeMergeInputData input = new EdgeMergeInputData();
private static final int A1_EDGECHANGE_NB = 19;
- private static final int A1_ASSOCHANGE_NB = 13;
+ private static final int A1_ASSOCHANGE_NB = 14;
private static final int A1_DIFFS_NB = A1_EDGECHANGE_NB + A1_ASSOCHANGE_NB;
private static final int A2_EDGECHANGE_NB = 19;
private static final int A2_NODECHANGE_NB = 26;
- private static final int A2_ASSOCHANGE_NB = 13;
+ private static final int A2_ASSOCHANGE_NB = 14;
private static final int A2_CLASSCHANGE_NB = 1;
private static final int A2_DIFFS_NB = A2_EDGECHANGE_NB + A2_NODECHANGE_NB + A2_ASSOCHANGE_NB + A2_CLASSCHANGE_NB;
@@ -106,8 +106,10 @@ public class EdgeMergeTest extends AbstractTest {
private static final int A6_CLASSCHANGE1_NB = 1;
private static final int A6_CLASSCHANGES_NB = 2 * A6_CLASSCHANGE1_NB;
private static final int A6_DEPENDENCY_CHANGE1_NB = 5;
- private static final int A6_DEPENDENCY_CHANGES_NB = 11 * A6_DEPENDENCY_CHANGE1_NB;
- private static final int A6_ASSO_CHANGE1_NB = 13;
+ private static final int A6_SUBSTITUTION_CHANGE1_NB = 6;
+ private static final int A6_IREAL_CHANGE1_NB = 6;
+ private static final int A6_DEPENDENCY_CHANGES_NB = 8 * A6_DEPENDENCY_CHANGE1_NB + 2 * A6_SUBSTITUTION_CHANGE1_NB + A6_IREAL_CHANGE1_NB;
+ private static final int A6_ASSO_CHANGE1_NB = 14;
private static final int A6_ASSO_CHANGES_NB = 2 * A6_ASSO_CHANGE1_NB;
private static final int A6_IMPORT_CHANGE1_NB = 2;
private static final int A6_IMPORT_CHANGES_NB = 2 * A6_IMPORT_CHANGE1_NB;
@@ -141,8 +143,8 @@ public class EdgeMergeTest extends AbstractTest {
getMergerRegistry().getHighestRankingMerger(edgeChange).copyLeftToRight(edgeChange, new BasicMonitor());
// ** MERGE CHECKING **
- comparison = buildComparison(left, right);
- diffsChecking(comparison, 0); // all diffs merged
+ comparison = buildComparison(left, right);
+ diffsCheckingBug410737(comparison, 0); // all diffs merged
}
@Test
@@ -164,7 +166,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A1_DIFFS_NB - A1_EDGECHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge, 0)); // only graphical diffs merged
+ diffsCheckingBug410737(comparison, A1_DIFFS_NB - A1_EDGECHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge, 0)); // only graphical diffs merged
}
@Test
@@ -186,7 +188,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A1_DIFFS_NB - A1_EDGECHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge, 0)); // only graphical diffs merged
+ diffsCheckingBug410737(comparison, A1_DIFFS_NB - A1_EDGECHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge, 0)); // only graphical diffs merged
}
@Test
@@ -208,7 +210,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, 0); // all diffs merged
+ diffsCheckingBug410737(comparison, 0); // all diffs merged
}
@Test
@@ -230,7 +232,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A1_DIFFS_NB - A1_ASSOCHANGE_NB); // only 13 semantic diffs merged
+ diffsCheckingBug410737(comparison, A1_DIFFS_NB - A1_ASSOCHANGE_NB); // only 13 semantic diffs merged
}
@Test
@@ -252,7 +254,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, 0); // all diffs merged
+ diffsCheckingBug410737(comparison, 0); // all diffs merged
}
@Test
@@ -274,7 +276,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, 0); // all diffs merged
+ diffsCheckingBug410737(comparison, 0); // all diffs merged
}
@Test
@@ -296,7 +298,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A1_DIFFS_NB - A1_ASSOCHANGE_NB); // only 13 semantic diffs merged
+ diffsCheckingBug410737(comparison, A1_DIFFS_NB - A1_ASSOCHANGE_NB); // only 13 semantic diffs merged
}
@Test
@@ -319,7 +321,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, 0); // all diffs merged
+ diffsCheckingBug410737(comparison, 0); // all diffs merged
}
@Test
@@ -342,7 +344,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A2_DIFFS_NB - A2_EDGECHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge, 0), new ExpectedStat(node, 1));
+ diffsCheckingBug410737(comparison, A2_DIFFS_NB - A2_EDGECHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge, 0), new ExpectedStat(node, 1));
}
@Test
@@ -365,7 +367,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A2_DIFFS_NB - A2_EDGECHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge, 0), new ExpectedStat(node, 1));
+ diffsCheckingBug410737(comparison, A2_DIFFS_NB - A2_EDGECHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge, 0), new ExpectedStat(node, 1));
}
@Test
@@ -388,7 +390,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, 0); // all diffs merged
+ diffsCheckingBug410737(comparison, 0); // all diffs merged
}
@Test
@@ -411,7 +413,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A2_DIFFS_NB - A2_ASSOCHANGE_NB - A2_CLASSCHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 1), new ExpectedStat(node, 1));
+ diffsCheckingBug410737(comparison, A2_DIFFS_NB - A2_ASSOCHANGE_NB - A2_CLASSCHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 1), new ExpectedStat(node, 1));
}
@Test
@@ -434,7 +436,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A2_DIFFS_NB - A2_ASSOCHANGE_NB - A2_EDGECHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 0), new ExpectedStat(node, 1));
+ diffsCheckingBug410737(comparison, A2_DIFFS_NB - A2_ASSOCHANGE_NB - A2_EDGECHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 0), new ExpectedStat(node, 1));
}
@Test
@@ -457,7 +459,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A2_DIFFS_NB - A2_ASSOCHANGE_NB - A2_EDGECHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 0), new ExpectedStat(node, 1));
+ diffsCheckingBug410737(comparison, A2_DIFFS_NB - A2_ASSOCHANGE_NB - A2_EDGECHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 0), new ExpectedStat(node, 1));
}
@Test
@@ -480,7 +482,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A2_DIFFS_NB - A2_ASSOCHANGE_NB - A2_CLASSCHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 1), new ExpectedStat(node, 1));
+ diffsCheckingBug410737(comparison, A2_DIFFS_NB - A2_ASSOCHANGE_NB - A2_CLASSCHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 1), new ExpectedStat(node, 1));
}
@Test
@@ -503,7 +505,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, 0); // all diffs merged
+ diffsCheckingBug410737(comparison, 0); // all diffs merged
}
@Test
@@ -526,7 +528,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A3_DIFFS_NB - A3_EDGECHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge, 0), new ExpectedStat(node, 2));
+ diffsCheckingBug410737(comparison, A3_DIFFS_NB - A3_EDGECHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge, 0), new ExpectedStat(node, 2));
}
@Test
@@ -549,7 +551,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A3_DIFFS_NB - A3_EDGECHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge, 0), new ExpectedStat(node, 2));
+ diffsCheckingBug410737(comparison, A3_DIFFS_NB - A3_EDGECHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge, 0), new ExpectedStat(node, 2));
}
@Test
@@ -572,7 +574,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, 0); // all diffs merged
+ diffsCheckingBug410737(comparison, 0); // all diffs merged
}
@Test
@@ -595,7 +597,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A3_DIFFS_NB - A3_ASSOCHANGE_NB - A3_CLASSCHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 1), new ExpectedStat(node, 2));
+ diffsCheckingBug410737(comparison, A3_DIFFS_NB - A3_ASSOCHANGE_NB - A3_CLASSCHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 1), new ExpectedStat(node, 2));
}
@Test
@@ -618,7 +620,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A3_DIFFS_NB - A3_ASSOCHANGE_NB - A3_EDGECHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 0), new ExpectedStat(node, 2));
+ diffsCheckingBug410737(comparison, A3_DIFFS_NB - A3_ASSOCHANGE_NB - A3_EDGECHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 0), new ExpectedStat(node, 2));
}
@Test
@@ -641,7 +643,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A3_DIFFS_NB - A3_ASSOCHANGE_NB - A3_EDGECHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 0), new ExpectedStat(node, 2));
+ diffsCheckingBug410737(comparison, A3_DIFFS_NB - A3_ASSOCHANGE_NB - A3_EDGECHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 0), new ExpectedStat(node, 2));
}
@Test
@@ -664,7 +666,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A3_DIFFS_NB - A3_ASSOCHANGE_NB - A3_CLASSCHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 1), new ExpectedStat(node, 2));
+ diffsCheckingBug410737(comparison, A3_DIFFS_NB - A3_ASSOCHANGE_NB - A3_CLASSCHANGE_NB, new ExpectedStat(association, 0), new ExpectedStat(edge, 1), new ExpectedStat(node, 2));
}
@Test
@@ -688,7 +690,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A4_DIFFS_NB - A4_EDGECHANGE1_NB - A4_NODECHANGE1_NB - A4_PKGNODECHANGE_NB - A4_ASSOCHANGE1_NB - A4_CLASSCHANGE1_NB - A4_PKGCHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge1, 0), new ExpectedStat(edge2, 1), new ExpectedStat(node, 3));
+ diffsCheckingBug410737(comparison, A4_DIFFS_NB - A4_EDGECHANGE1_NB - A4_NODECHANGE1_NB - A4_PKGNODECHANGE_NB - A4_ASSOCHANGE1_NB - A4_CLASSCHANGE1_NB - A4_PKGCHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge1, 0), new ExpectedStat(edge2, 1), new ExpectedStat(node, 3));
}
@Test
@@ -712,7 +714,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A4_DIFFS_NB - A4_EDGECHANGE1_NB, new ExpectedStat(association, 2), new ExpectedStat(edge1, 0), new ExpectedStat(edge2, 1), new ExpectedStat(node, 5));
+ diffsCheckingBug410737(comparison, A4_DIFFS_NB - A4_EDGECHANGE1_NB, new ExpectedStat(association, 2), new ExpectedStat(edge1, 0), new ExpectedStat(edge2, 1), new ExpectedStat(node, 5));
}
@Test
@@ -736,7 +738,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A4_DIFFS_NB - A4_EDGECHANGE1_NB, new ExpectedStat(association, 2), new ExpectedStat(edge1, 0), new ExpectedStat(edge2, 1), new ExpectedStat(node, 5));
+ diffsCheckingBug410737(comparison, A4_DIFFS_NB - A4_EDGECHANGE1_NB, new ExpectedStat(association, 2), new ExpectedStat(edge1, 0), new ExpectedStat(edge2, 1), new ExpectedStat(node, 5));
}
@Test
@@ -760,7 +762,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A4_DIFFS_NB - A4_EDGECHANGE1_NB - A4_NODECHANGE1_NB - A4_PKGNODECHANGE_NB - A4_ASSOCHANGE1_NB - A4_CLASSCHANGE1_NB - A4_PKGCHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge1, 0), new ExpectedStat(edge2, 1), new ExpectedStat(node, 3));
+ diffsCheckingBug410737(comparison, A4_DIFFS_NB - A4_EDGECHANGE1_NB - A4_NODECHANGE1_NB - A4_PKGNODECHANGE_NB - A4_ASSOCHANGE1_NB - A4_CLASSCHANGE1_NB - A4_PKGCHANGE_NB, new ExpectedStat(association, 1), new ExpectedStat(edge1, 0), new ExpectedStat(edge2, 1), new ExpectedStat(node, 3));
}
@Test
@@ -785,7 +787,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A4_DIFFS_NB - A4_ASSOCHANGE1_NB - A4_CLASSCHANGE1_NB - A4_PKGCHANGE_NB, new ExpectedStat(asso1, 0), new ExpectedStat(asso2, 1), new ExpectedStat(edge1, 1), new ExpectedStat(edge2, 1), new ExpectedStat(node, 5));
+ diffsCheckingBug410737(comparison, A4_DIFFS_NB - A4_ASSOCHANGE1_NB - A4_CLASSCHANGE1_NB - A4_PKGCHANGE_NB, new ExpectedStat(asso1, 0), new ExpectedStat(asso2, 1), new ExpectedStat(edge1, 1), new ExpectedStat(edge2, 1), new ExpectedStat(node, 5));
}
@Test
@@ -810,7 +812,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A4_DIFFS_NB - A4_ASSOCHANGE1_NB - A4_EDGECHANGE1_NB, new ExpectedStat(asso1, 0), new ExpectedStat(asso2, 1), new ExpectedStat(edge1, 0), new ExpectedStat(edge2, 1), new ExpectedStat(node, 5));
+ diffsCheckingBug410737(comparison, A4_DIFFS_NB - A4_ASSOCHANGE1_NB - A4_EDGECHANGE1_NB, new ExpectedStat(asso1, 0), new ExpectedStat(asso2, 1), new ExpectedStat(edge1, 0), new ExpectedStat(edge2, 1), new ExpectedStat(node, 5));
}
@Test
@@ -835,7 +837,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A4_DIFFS_NB - A4_ASSOCHANGE1_NB - A4_EDGECHANGE1_NB, new ExpectedStat(asso1, 0), new ExpectedStat(asso2, 1), new ExpectedStat(edge1, 0), new ExpectedStat(edge2, 1), new ExpectedStat(node, 5));
+ diffsCheckingBug410737(comparison, A4_DIFFS_NB - A4_ASSOCHANGE1_NB - A4_EDGECHANGE1_NB, new ExpectedStat(asso1, 0), new ExpectedStat(asso2, 1), new ExpectedStat(edge1, 0), new ExpectedStat(edge2, 1), new ExpectedStat(node, 5));
}
@Test
@@ -860,7 +862,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A4_DIFFS_NB - A4_ASSOCHANGE1_NB - A4_CLASSCHANGE1_NB - A4_PKGCHANGE_NB, new ExpectedStat(asso1, 0), new ExpectedStat(asso2, 1), new ExpectedStat(edge1, 1), new ExpectedStat(edge2, 1), new ExpectedStat(node, 5));
+ diffsCheckingBug410737(comparison, A4_DIFFS_NB - A4_ASSOCHANGE1_NB - A4_CLASSCHANGE1_NB - A4_PKGCHANGE_NB, new ExpectedStat(asso1, 0), new ExpectedStat(asso2, 1), new ExpectedStat(edge1, 1), new ExpectedStat(edge2, 1), new ExpectedStat(node, 5));
}
@Test
@@ -887,7 +889,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A4_DIFFS_NB - A4_NODECHANGE1_NB - A4_PKGNODECHANGE_NB - A4_CLASSCHANGE1_NB - A4_PKGCHANGE_NB, new ExpectedStat(asso1, 1), new ExpectedStat(asso2, 1), new ExpectedStat(edge1, 1), new ExpectedStat(edge2, 1), new ExpectedStat(nodeB, 0), new ExpectedStat(nodeSubB, 1), new ExpectedStat(nodePropB, 1));
+ diffsCheckingBug410737(comparison, A4_DIFFS_NB - A4_NODECHANGE1_NB - A4_PKGNODECHANGE_NB - A4_CLASSCHANGE1_NB - A4_PKGCHANGE_NB, new ExpectedStat(asso1, 1), new ExpectedStat(asso2, 1), new ExpectedStat(edge1, 1), new ExpectedStat(edge2, 1), new ExpectedStat(nodeB, 0), new ExpectedStat(nodeSubB, 1), new ExpectedStat(nodePropB, 1));
}
@Test
@@ -914,7 +916,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A4_DIFFS_NB - A4_NODECHANGE1_NB - 2 * A4_EDGECHANGE1_NB - A4_PROPNODECHANGE_NB - A4_SUBNODECHANGE_NB, new ExpectedStat(asso1, 1), new ExpectedStat(asso2, 1), new ExpectedStat(edge1, 0), new ExpectedStat(edge2, 0), new ExpectedStat(nodeB, 0), new ExpectedStat(nodeSubB, 0), new ExpectedStat(nodePropB, 0));
+ diffsCheckingBug410737(comparison, A4_DIFFS_NB - A4_NODECHANGE1_NB - 2 * A4_EDGECHANGE1_NB - A4_PROPNODECHANGE_NB - A4_SUBNODECHANGE_NB, new ExpectedStat(asso1, 1), new ExpectedStat(asso2, 1), new ExpectedStat(edge1, 0), new ExpectedStat(edge2, 0), new ExpectedStat(nodeB, 0), new ExpectedStat(nodeSubB, 0), new ExpectedStat(nodePropB, 0));
}
@Test
@@ -967,7 +969,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A6_DIFFS_NB - A6_DEPENDENCY_EDGE_CHANGE1_NB - A6_DEPENDENCY_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
+ diffsCheckingBug410737(comparison, A6_DIFFS_NB - A6_DEPENDENCY_EDGE_CHANGE1_NB - A6_DEPENDENCY_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
new ExpectedStat(substitutions, 2),
new ExpectedStat(interfaceRealizations, 1),
new ExpectedStat(associations, 2),
@@ -1035,7 +1037,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A6_DIFFS_NB - A6_ASSO_EDGE_CHANGE1_NB - A6_ASSO_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
+ diffsCheckingBug410737(comparison, A6_DIFFS_NB - A6_ASSO_EDGE_CHANGE1_NB - A6_ASSO_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
new ExpectedStat(substitutions, 2),
new ExpectedStat(interfaceRealizations, 1),
new ExpectedStat(associations, 1), // ** -1
@@ -1103,7 +1105,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A6_DIFFS_NB - A6_DEPENDENCY_EDGE_CHANGE1_NB - A6_DEPENDENCY_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
+ diffsCheckingBug410737(comparison, A6_DIFFS_NB - A6_DEPENDENCY_EDGE_CHANGE1_NB - A6_DEPENDENCY_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
new ExpectedStat(substitutions, 2),
new ExpectedStat(interfaceRealizations, 1),
new ExpectedStat(associations, 2),
@@ -1123,6 +1125,7 @@ public class EdgeMergeTest extends AbstractTest {
@Test
@Ignore
+ // FIXME See Bug 406405
// Merge Left to Right <ADD Import Edge>
public void testA6d() throws IOException {
final Resource left = input.getA6EdgeChangeLeft();
@@ -1173,7 +1176,8 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
//FIXME: ElementImport.importedElement is not merged => should create a UMLDiff for this DirectedRelationship (A6_IMPORT_CHANGE1_NB += 1)
- diffsChecking(comparison, A6_DIFFS_NB - A6_IMPORT_EDGE_CHANGE1_NB - A6_IMPORT_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
+ // See Bug 406405
+ diffsCheckingBug410737(comparison, A6_DIFFS_NB - A6_IMPORT_EDGE_CHANGE1_NB - A6_IMPORT_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
new ExpectedStat(substitutions, 2),
new ExpectedStat(interfaceRealizations, 1),
new ExpectedStat(associations, 2),
@@ -1193,6 +1197,7 @@ public class EdgeMergeTest extends AbstractTest {
@Test
@Ignore
+ // FIXME See Bug 406405
// Merge Left to Right <ADD Generalization Edge>
public void testA6e() throws IOException {
final Resource left = input.getA6EdgeChangeLeft();
@@ -1243,7 +1248,8 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
//FIXME: Generalization.general is not merged => should create a UMLDiff for this DirectedRelationship (A6_GENERAL_CHANGE1_NB += 1)
- diffsChecking(comparison, A6_DIFFS_NB - A6_GENERAL_EDGE_CHANGE1_NB - A6_GENERAL_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
+ // See Bug 406405
+ diffsCheckingBug410737(comparison, A6_DIFFS_NB - A6_GENERAL_EDGE_CHANGE1_NB - A6_GENERAL_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
new ExpectedStat(substitutions, 2),
new ExpectedStat(interfaceRealizations, 1),
new ExpectedStat(associations, 2),
@@ -1263,6 +1269,7 @@ public class EdgeMergeTest extends AbstractTest {
@Test
@Ignore
+ // FIXME See Bug 406405
// Merge Left to Right <ADD Flow Edge>
public void testA6f() throws IOException {
final Resource left = input.getA6EdgeChangeLeft();
@@ -1313,6 +1320,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
//FIXME: InformationFlow.informationSource and InformationFlow.informationTarget are not merged => should create a UMLDiff for this DirectedRelationship (A6_FLOW_CHANGE1_NB += 2)
+ // See Bug 406405
diffsChecking(comparison, A6_DIFFS_NB - A6_FLOW_EDGE_CHANGE1_NB - A6_FLOW_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
new ExpectedStat(substitutions, 2),
new ExpectedStat(interfaceRealizations, 1),
@@ -1381,7 +1389,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A6_DIFFS_NB - A6_DEPENDENCY_EDGE_CHANGE1_NB - A6_DEPENDENCY_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
+ diffsCheckingBug410737(comparison, A6_DIFFS_NB - A6_DEPENDENCY_EDGE_CHANGE1_NB - A6_IREAL_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
new ExpectedStat(substitutions, 2),
new ExpectedStat(interfaceRealizations, 0), // ** -1
new ExpectedStat(associations, 2),
@@ -1449,7 +1457,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A6_DIFFS_NB - A6_DEPENDENCY_EDGE_CHANGE1_NB - A6_DEPENDENCY_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
+ diffsCheckingBug410737(comparison, A6_DIFFS_NB - A6_DEPENDENCY_EDGE_CHANGE1_NB - A6_DEPENDENCY_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
new ExpectedStat(substitutions, 2),
new ExpectedStat(interfaceRealizations, 1),
new ExpectedStat(associations, 2),
@@ -1517,7 +1525,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A6_DIFFS_NB - A6_DEPENDENCY_EDGE_CHANGE1_NB - A6_DEPENDENCY_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
+ diffsCheckingBug410737(comparison, A6_DIFFS_NB - A6_DEPENDENCY_EDGE_CHANGE1_NB - A6_SUBSTITUTION_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
new ExpectedStat(substitutions, 1), // ** -1
new ExpectedStat(interfaceRealizations, 1),
new ExpectedStat(associations, 2),
@@ -1585,7 +1593,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A6_DIFFS_NB - A6_DEPENDENCY_EDGE_CHANGE1_NB - A6_DEPENDENCY_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
+ diffsCheckingBug410737(comparison, A6_DIFFS_NB - A6_DEPENDENCY_EDGE_CHANGE1_NB - A6_DEPENDENCY_CHANGE1_NB - A6_NODECHANGE1_NB - A6_CLASSCHANGE1_NB,
new ExpectedStat(substitutions, 2),
new ExpectedStat(interfaceRealizations, 1),
new ExpectedStat(associations, 2),
@@ -1630,7 +1638,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A7_DIFFS_NB - A7_EDGECHANGE1_NB,
+ diffsCheckingBug410737(comparison, A7_DIFFS_NB - A7_EDGECHANGE1_NB,
new ExpectedStat(edges, 2), // ** -1
new ExpectedStat(edgeTarget, 1),
new ExpectedStat(assoTarget, 1));
@@ -1663,7 +1671,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A7_DIFFS_NB - A7_EDGECHANGE1_NB,
+ diffsCheckingBug410737(comparison, A7_DIFFS_NB - A7_EDGECHANGE1_NB,
new ExpectedStat(edges, 2), // ** -1
new ExpectedStat(edgeTarget, 1),
new ExpectedStat(assoTarget, 1));
@@ -1696,7 +1704,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A7_DIFFS_NB - A7_EDGECHANGE1_NB,
+ diffsCheckingBug410737(comparison, A7_DIFFS_NB - A7_EDGECHANGE1_NB,
new ExpectedStat(edges, 2), // ** -1
new ExpectedStat(edgeTarget, 1),
new ExpectedStat(assoTarget, 1));
@@ -1729,7 +1737,7 @@ public class EdgeMergeTest extends AbstractTest {
// ** MERGE CHECKING **
comparison = buildComparison(left, right);
- diffsChecking(comparison, A7_DIFFS_NB - A7_EDGE_TARGET_CHANGE_NB,
+ diffsCheckingBug410737(comparison, A7_DIFFS_NB - A7_EDGE_TARGET_CHANGE_NB,
new ExpectedStat(edges, 3),
new ExpectedStat(edgeTarget, 0), // ** -1
new ExpectedStat(assoTarget, 1));
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/NodeMergeTest.java b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/NodeMergeTest.java
index 1d24c0c2e..11e89643f 100644
--- a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/NodeMergeTest.java
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/NodeMergeTest.java
@@ -109,7 +109,7 @@ public class NodeMergeTest extends AbstractTest {
private static final int A1_ELTCHANGES_NB = 8 * A1_ELTCHANGE1_NB;
- private static final int A1_ASSOCHANGE1_NB = 13;
+ private static final int A1_ASSOCHANGE1_NB = 14;
private static final int A1_ASSOCHANGES_NB = 3 * A1_ASSOCHANGE1_NB;
@@ -1338,7 +1338,8 @@ public class NodeMergeTest extends AbstractTest {
}
@Test
- @Ignore // bug in core (data set sent to MBA 2013-04-22)
+ @Ignore
+ // FIXME See Bug 406402
// Successive merges right to left of NodeLists
public void testA4b() throws IOException {
final Resource left = input.getA4NodeChangeLeft();
@@ -1424,7 +1425,8 @@ public class NodeMergeTest extends AbstractTest {
}
@Test
- @Ignore // bug in core (data set sent to MBA 2013-04-22)
+ @Ignore
+ // FIXME See Bug 406402
// Successive merges left to right of NodeLists
public void testA4c() throws IOException {
final Resource left = input.getA4NodeChangeLeft();
diff --git a/plugins/org.eclipse.emf.compare.edit/plugin.properties b/plugins/org.eclipse.emf.compare.edit/plugin.properties
index ed6adc31b..c44348a01 100644
--- a/plugins/org.eclipse.emf.compare.edit/plugin.properties
+++ b/plugins/org.eclipse.emf.compare.edit/plugin.properties
@@ -84,3 +84,5 @@ _UI_DifferenceState_MERGED_literal = MERGED
_UI_DifferenceState_DISCARDED_literal = DISCARDED
_UI_Comparison_threeWay_feature = Three Way
_UI_MatchResource_comparison_feature = Comparison
+_UI_Diff_implies_feature = Implies
+_UI_Diff_impliedBy_feature = Implied By
diff --git a/plugins/org.eclipse.emf.compare.edit/src-gen/org/eclipse/emf/compare/provider/DiffItemProvider.java b/plugins/org.eclipse.emf.compare.edit/src-gen/org/eclipse/emf/compare/provider/DiffItemProvider.java
index dbdf0e45f..787d0da70 100644
--- a/plugins/org.eclipse.emf.compare.edit/src-gen/org/eclipse/emf/compare/provider/DiffItemProvider.java
+++ b/plugins/org.eclipse.emf.compare.edit/src-gen/org/eclipse/emf/compare/provider/DiffItemProvider.java
@@ -74,6 +74,8 @@ public class DiffItemProvider extends ItemProviderAdapter implements IEditingDom
addRequiresPropertyDescriptor(object);
addRequiredByPropertyDescriptor(object);
+ addImpliesPropertyDescriptor(object);
+ addImpliedByPropertyDescriptor(object);
addRefinesPropertyDescriptor(object);
addRefinedByPropertyDescriptor(object);
addKindPropertyDescriptor(object);
@@ -120,6 +122,36 @@ public class DiffItemProvider extends ItemProviderAdapter implements IEditingDom
}
/**
+ * This adds a property descriptor for the Implies feature.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ protected void addImpliesPropertyDescriptor(Object object) {
+ itemPropertyDescriptors.add(createItemPropertyDescriptor(((ComposeableAdapterFactory)adapterFactory)
+ .getRootAdapterFactory(), getResourceLocator(), getString("_UI_Diff_implies_feature"), //$NON-NLS-1$
+ getString("_UI_PropertyDescriptor_description", "_UI_Diff_implies_feature", "_UI_Diff_type"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ ComparePackage.Literals.DIFF__IMPLIES, true, false, true, null, null, null));
+ }
+
+ /**
+ * This adds a property descriptor for the Implied By feature.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ protected void addImpliedByPropertyDescriptor(Object object) {
+ itemPropertyDescriptors
+ .add(createItemPropertyDescriptor(((ComposeableAdapterFactory)adapterFactory)
+ .getRootAdapterFactory(),
+ getResourceLocator(),
+ getString("_UI_Diff_impliedBy_feature"), //$NON-NLS-1$
+ getString(
+ "_UI_PropertyDescriptor_description", "_UI_Diff_impliedBy_feature", "_UI_Diff_type"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ ComparePackage.Literals.DIFF__IMPLIED_BY, true, false, true, null, null, null));
+ }
+
+ /**
* This adds a property descriptor for the Refines feature.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/table/TableContentMergeViewer.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/table/TableContentMergeViewer.java
index 83ffa1e9a..68a7c512a 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/table/TableContentMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/table/TableContentMergeViewer.java
@@ -20,13 +20,13 @@ import org.eclipse.compare.CompareConfiguration;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer;
+import org.eclipse.emf.compare.internal.utils.ComparisonUtil;
import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin;
import org.eclipse.emf.compare.rcp.ui.internal.contentmergeviewer.accessor.ICompareAccessor;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.IMergeViewer.MergeViewerSide;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl.AbstractMergeViewer;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl.TableMergeViewer;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.item.IMergeViewerItem;
-import org.eclipse.emf.compare.utils.DiffUtil;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
@@ -118,7 +118,7 @@ public class TableContentMergeViewer extends EMFCompareContentMergeViewer {
List<Diff> diffsToCopy = new ArrayList<Diff>();
diffsToCopy.add(diffToCopy);
if (isSubDiffFilterActive()) {
- addAll(diffsToCopy, DiffUtil.getSubDiffs(leftToRight).apply(diffToCopy));
+ addAll(diffsToCopy, ComparisonUtil.getSubDiffs(leftToRight).apply(diffToCopy));
}
Command copyCommand = getEditingDomain().createCopyCommand(diffsToCopy, leftToRight,
EMFCompareRCPPlugin.getDefault().getMergerRegistry());
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/tree/TreeContentMergeViewer.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/tree/TreeContentMergeViewer.java
index ff4f26946..d3f6cd792 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/tree/TreeContentMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/tree/TreeContentMergeViewer.java
@@ -30,6 +30,7 @@ import org.eclipse.emf.compare.DifferenceKind;
import org.eclipse.emf.compare.Match;
import org.eclipse.emf.compare.ReferenceChange;
import org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer;
+import org.eclipse.emf.compare.internal.utils.ComparisonUtil;
import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin;
import org.eclipse.emf.compare.rcp.ui.internal.contentmergeviewer.accessor.ICompareAccessor;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.IMergeViewer.MergeViewerSide;
@@ -38,7 +39,6 @@ import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl.TreeMergeViewer;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.item.IMergeViewerItem;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.item.impl.MergeViewerItem;
import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.filters.IDifferenceFilter;
-import org.eclipse.emf.compare.utils.DiffUtil;
import org.eclipse.emf.compare.utils.EMFComparePredicates;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
@@ -181,7 +181,7 @@ public class TreeContentMergeViewer extends EMFCompareContentMergeViewer {
List<Diff> diffsToCopy = new ArrayList<Diff>();
diffsToCopy.add(diffToCopy);
if (isSubDiffFilterActive()) {
- addAll(diffsToCopy, DiffUtil.getSubDiffs(leftToRight).apply(diffToCopy));
+ addAll(diffsToCopy, ComparisonUtil.getSubDiffs(leftToRight).apply(diffToCopy));
}
Command copyCommand = getEditingDomain().createCopyCommand(diffsToCopy, leftToRight,
EMFCompareRCPPlugin.getDefault().getMergerRegistry());
@@ -398,7 +398,7 @@ public class TreeContentMergeViewer extends EMFCompareContentMergeViewer {
}
}
if (doPaint) {
- if (leftDiff != null) {
+ if (leftDiff != null) {
TreeItem rightItem = findRightTreeItemFromLeftDiff(rightItems, leftDiff, leftData);
if (rightItem != null) {
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/contentmergeviewer/accessor/impl/ManyStructuralFeatureAccessorImpl.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/contentmergeviewer/accessor/impl/ManyStructuralFeatureAccessorImpl.java
index 8729824c3..7d6ef957c 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/contentmergeviewer/accessor/impl/ManyStructuralFeatureAccessorImpl.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/contentmergeviewer/accessor/impl/ManyStructuralFeatureAccessorImpl.java
@@ -25,10 +25,10 @@ import org.eclipse.emf.compare.AttributeChange;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.Match;
import org.eclipse.emf.compare.ReferenceChange;
+import org.eclipse.emf.compare.internal.utils.DiffUtil;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.IMergeViewer.MergeViewerSide;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.item.IMergeViewerItem;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.item.impl.MergeViewerItem;
-import org.eclipse.emf.compare.utils.DiffUtil;
import org.eclipse.emf.compare.utils.IEqualityHelper;
import org.eclipse.emf.compare.utils.ReferenceUtil;
import org.eclipse.emf.ecore.EObject;
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/MergeViewerItem.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/MergeViewerItem.java
index 6191dc478..1250e389a 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/MergeViewerItem.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/MergeViewerItem.java
@@ -42,11 +42,11 @@ import org.eclipse.emf.compare.Match;
import org.eclipse.emf.compare.ReferenceChange;
import org.eclipse.emf.compare.ResourceAttachmentChange;
import org.eclipse.emf.compare.internal.spec.EObjectUtil;
+import org.eclipse.emf.compare.internal.utils.DiffUtil;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.IMergeViewer.MergeViewerSide;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.item.IMergeViewerItem;
import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.filters.IDifferenceFilter;
import org.eclipse.emf.compare.rcp.ui.internal.util.MergeViewerUtil;
-import org.eclipse.emf.compare.utils.DiffUtil;
import org.eclipse.emf.compare.utils.ReferenceUtil;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/ResourceAttachmentChangeMergeViewerItem.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/ResourceAttachmentChangeMergeViewerItem.java
index ce3a82ed1..c64a7b3c6 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/ResourceAttachmentChangeMergeViewerItem.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/ResourceAttachmentChangeMergeViewerItem.java
@@ -29,12 +29,12 @@ import org.eclipse.emf.compare.DifferenceSource;
import org.eclipse.emf.compare.DifferenceState;
import org.eclipse.emf.compare.Match;
import org.eclipse.emf.compare.ResourceAttachmentChange;
+import org.eclipse.emf.compare.internal.utils.DiffUtil;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.IMergeViewer;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.IMergeViewer.MergeViewerSide;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.item.IMergeViewerItem;
import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.filters.IDifferenceFilter;
import org.eclipse.emf.compare.rcp.ui.internal.util.MergeViewerUtil;
-import org.eclipse.emf.compare.utils.DiffUtil;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/diff/ComparisonUtilTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/diff/ComparisonUtilTest.java
new file mode 100644
index 000000000..098875513
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/diff/ComparisonUtilTest.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 Obeo.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.tests.diff;
+
+import static com.google.common.base.Predicates.and;
+import static junit.framework.Assert.assertEquals;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.ofKind;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.referenceValueMatch;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.DifferenceKind;
+import org.eclipse.emf.compare.DifferenceSource;
+import org.eclipse.emf.compare.EMFCompare;
+import org.eclipse.emf.compare.internal.utils.ComparisonUtil;
+import org.eclipse.emf.compare.scope.DefaultComparisonScope;
+import org.eclipse.emf.compare.scope.IComparisonScope;
+import org.eclipse.emf.compare.tests.fullcomparison.data.identifier.IdentifierMatchInputData;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.junit.Test;
+
+@SuppressWarnings("all")
+public class ComparisonUtilTest {
+ @Test
+ public void testSubDiffs() throws IOException {
+ IdentifierMatchInputData inputData = new IdentifierMatchInputData();
+
+ final Resource left = inputData.getExtlibraryLeft();
+ final Resource origin = inputData.getExtlibraryOrigin();
+ final Resource right = inputData.getExtlibraryRight();
+
+ // 2-way
+ IComparisonScope scope = new DefaultComparisonScope(left, right, null);
+ Comparison comparison = EMFCompare.builder().build().compare(scope);
+ List<Diff> differences = comparison.getDifferences();
+
+ // Right to left on a deleted element
+ final Predicate<? super Diff> leftPeriodical = and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.DELETE), referenceValueMatch("eClassifiers", "extlibrary.Periodical",
+ true));
+ final Diff leftPeriodicalDiff = Iterators.find(differences.iterator(), leftPeriodical);
+ boolean leftToRight = false;
+ Iterable<Diff> subDiffs = ComparisonUtil.getSubDiffs(leftToRight).apply(leftPeriodicalDiff);
+
+ assertEquals(7, Iterables.size(subDiffs));
+
+ // Left to right on a deleted element
+ leftToRight = true;
+ subDiffs = ComparisonUtil.getSubDiffs(leftToRight).apply(leftPeriodicalDiff);
+
+ assertEquals(4, Iterables.size(subDiffs));
+
+ // Right to left on an added element
+ final Predicate<? super Diff> leftMagazine = and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.ADD), referenceValueMatch("eClassifiers", "extlibrary.Magazine", true));
+ final Diff leftMagazineDiff = Iterators.find(differences.iterator(), leftMagazine);
+ leftToRight = false;
+ subDiffs = ComparisonUtil.getSubDiffs(leftToRight).apply(leftMagazineDiff);
+
+ assertEquals(5, Iterables.size(subDiffs));
+
+ // Left to right on an added element
+ leftToRight = true;
+ subDiffs = ComparisonUtil.getSubDiffs(leftToRight).apply(leftMagazineDiff);
+
+ assertEquals(5, Iterables.size(subDiffs));
+
+ // 3-way
+ scope = new DefaultComparisonScope(left, right, origin);
+ comparison = EMFCompare.builder().build().compare(scope);
+ differences = comparison.getDifferences();
+
+ // Right to left on a deleted element
+ final Predicate<? super Diff> leftPeriodical3Way = and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.DELETE), referenceValueMatch("eClassifiers", "extlibrary.Periodical",
+ true));
+ final Diff leftPeriodicalDiff3Way = Iterators.find(differences.iterator(), leftPeriodical3Way);
+ leftToRight = false;
+ subDiffs = ComparisonUtil.getSubDiffs(leftToRight).apply(leftPeriodicalDiff3Way);
+
+ assertEquals(11, Iterables.size(subDiffs));
+
+ // Left to right on a deleted element
+ leftToRight = true;
+ subDiffs = ComparisonUtil.getSubDiffs(leftToRight).apply(leftPeriodicalDiff3Way);
+
+ assertEquals(8, Iterables.size(subDiffs));
+
+ // Right to left on a added element
+ final Predicate<? super Diff> leftMagazine3Way = and(fromSide(DifferenceSource.LEFT),
+ ofKind(DifferenceKind.ADD), referenceValueMatch("eClassifiers", "extlibrary.Magazine", true));
+ final Diff leftMagazineDiff3Way = Iterators.find(differences.iterator(), leftMagazine3Way);
+ leftToRight = false;
+ subDiffs = ComparisonUtil.getSubDiffs(leftToRight).apply(leftMagazineDiff3Way);
+
+ assertEquals(5, Iterables.size(subDiffs));
+
+ // Left to right on an added element
+ leftToRight = true;
+ subDiffs = ComparisonUtil.getSubDiffs(leftToRight).apply(leftMagazineDiff3Way);
+
+ assertEquals(5, Iterables.size(subDiffs));
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/diff/DiffUtilTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/diff/DiffUtilTest.java
index 34cb0b6a7..60d65a22a 100644
--- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/diff/DiffUtilTest.java
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/diff/DiffUtilTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012 Obeo.
+ * Copyright (c) 2012, 2013 Obeo.
* 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
@@ -10,33 +10,17 @@
*******************************************************************************/
package org.eclipse.emf.compare.tests.diff;
-import static com.google.common.base.Predicates.and;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertSame;
import static junit.framework.Assert.fail;
-import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide;
-import static org.eclipse.emf.compare.utils.EMFComparePredicates.ofKind;
-import static org.eclipse.emf.compare.utils.EMFComparePredicates.referenceValueMatch;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
-import java.io.IOException;
import java.util.List;
import org.eclipse.emf.compare.CompareFactory;
import org.eclipse.emf.compare.Comparison;
-import org.eclipse.emf.compare.Diff;
-import org.eclipse.emf.compare.DifferenceKind;
-import org.eclipse.emf.compare.DifferenceSource;
-import org.eclipse.emf.compare.EMFCompare;
-import org.eclipse.emf.compare.scope.DefaultComparisonScope;
-import org.eclipse.emf.compare.scope.IComparisonScope;
-import org.eclipse.emf.compare.tests.fullcomparison.data.identifier.IdentifierMatchInputData;
-import org.eclipse.emf.compare.utils.DiffUtil;
-import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.compare.internal.utils.DiffUtil;
import org.junit.Test;
/**
@@ -477,87 +461,6 @@ public class DiffUtilTest {
}
}
- @Test
- public void testSubDiffs() throws IOException {
- IdentifierMatchInputData inputData = new IdentifierMatchInputData();
-
- final Resource left = inputData.getExtlibraryLeft();
- final Resource origin = inputData.getExtlibraryOrigin();
- final Resource right = inputData.getExtlibraryRight();
-
- // 2-way
- IComparisonScope scope = new DefaultComparisonScope(left, right, null);
- Comparison comparison = EMFCompare.builder().build().compare(scope);
- List<Diff> differences = comparison.getDifferences();
-
- // Right to left on a deleted element
- final Predicate<? super Diff> leftPeriodical = and(fromSide(DifferenceSource.LEFT),
- ofKind(DifferenceKind.DELETE), referenceValueMatch("eClassifiers", "extlibrary.Periodical",
- true));
- final Diff leftPeriodicalDiff = Iterators.find(differences.iterator(), leftPeriodical);
- boolean leftToRight = false;
- Iterable<Diff> subDiffs = DiffUtil.getSubDiffs(leftToRight).apply(leftPeriodicalDiff);
-
- assertEquals(7, Iterables.size(subDiffs));
-
- // Left to right on a deleted element
- leftToRight = true;
- subDiffs = DiffUtil.getSubDiffs(leftToRight).apply(leftPeriodicalDiff);
-
- assertEquals(4, Iterables.size(subDiffs));
-
- // Right to left on an added element
- final Predicate<? super Diff> leftMagazine = and(fromSide(DifferenceSource.LEFT),
- ofKind(DifferenceKind.ADD), referenceValueMatch("eClassifiers", "extlibrary.Magazine", true));
- final Diff leftMagazineDiff = Iterators.find(differences.iterator(), leftMagazine);
- leftToRight = false;
- subDiffs = DiffUtil.getSubDiffs(leftToRight).apply(leftMagazineDiff);
-
- assertEquals(5, Iterables.size(subDiffs));
-
- // Left to right on an added element
- leftToRight = true;
- subDiffs = DiffUtil.getSubDiffs(leftToRight).apply(leftMagazineDiff);
-
- assertEquals(5, Iterables.size(subDiffs));
-
- // 3-way
- scope = new DefaultComparisonScope(left, right, origin);
- comparison = EMFCompare.builder().build().compare(scope);
- differences = comparison.getDifferences();
-
- // Right to left on a deleted element
- final Predicate<? super Diff> leftPeriodical3Way = and(fromSide(DifferenceSource.LEFT),
- ofKind(DifferenceKind.DELETE), referenceValueMatch("eClassifiers", "extlibrary.Periodical",
- true));
- final Diff leftPeriodicalDiff3Way = Iterators.find(differences.iterator(), leftPeriodical3Way);
- leftToRight = false;
- subDiffs = DiffUtil.getSubDiffs(leftToRight).apply(leftPeriodicalDiff3Way);
-
- assertEquals(11, Iterables.size(subDiffs));
-
- // Left to right on a deleted element
- leftToRight = true;
- subDiffs = DiffUtil.getSubDiffs(leftToRight).apply(leftPeriodicalDiff3Way);
-
- assertEquals(8, Iterables.size(subDiffs));
-
- // Right to left on a added element
- final Predicate<? super Diff> leftMagazine3Way = and(fromSide(DifferenceSource.LEFT),
- ofKind(DifferenceKind.ADD), referenceValueMatch("eClassifiers", "extlibrary.Magazine", true));
- final Diff leftMagazineDiff3Way = Iterators.find(differences.iterator(), leftMagazine3Way);
- leftToRight = false;
- subDiffs = DiffUtil.getSubDiffs(leftToRight).apply(leftMagazineDiff3Way);
-
- assertEquals(5, Iterables.size(subDiffs));
-
- // Left to right on an added element
- leftToRight = true;
- subDiffs = DiffUtil.getSubDiffs(leftToRight).apply(leftMagazineDiff3Way);
-
- assertEquals(5, Iterables.size(subDiffs));
- }
-
public void diceCoefficientFailure() {
try {
DiffUtil.diceCoefficient(null, null);
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/suite/AllTests.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/suite/AllTests.java
index c9377fa13..77a7b1ba2 100644
--- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/suite/AllTests.java
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/suite/AllTests.java
@@ -17,6 +17,7 @@ import junit.textui.TestRunner;
import org.eclipse.emf.compare.ComparePackage;
import org.eclipse.emf.compare.tests.command.CommandStackTestSuite;
import org.eclipse.emf.compare.tests.conflict.ConflictDetectionTest;
+import org.eclipse.emf.compare.tests.diff.ComparisonUtilTest;
import org.eclipse.emf.compare.tests.diff.DiffUtilTest;
import org.eclipse.emf.compare.tests.diff.LCSPerformanceTest;
import org.eclipse.emf.compare.tests.diff.URIDistanceTest;
@@ -52,11 +53,11 @@ import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({CompareTestSuite.class, DefaultComparisonScopeTest.class, IdentifierComparisonTest.class,
ExtLibraryTest.class, ConflictDetectionTest.class, ReqComputingTest.class, EquiComputingTest.class,
- DiffUtilTest.class, LCSPerformanceTest.class, MultipleMergeTest.class, PostProcessorTest.class,
- IndividualMergeTest.class, ExtensionMergeTest.class, IndividualMergeOutOfScopeValuesTest.class,
- ProximityComparisonTest.class, DynamicInstanceComparisonTest.class, URIDistanceTest.class,
- FragmentationTest.class, AllEditTests.class, CommandStackTestSuite.class,
- MatchEngineFactoryRegistryTest.class })
+ DiffUtilTest.class, ComparisonUtilTest.class, LCSPerformanceTest.class, MultipleMergeTest.class,
+ PostProcessorTest.class, IndividualMergeTest.class, ExtensionMergeTest.class,
+ IndividualMergeOutOfScopeValuesTest.class, ProximityComparisonTest.class,
+ DynamicInstanceComparisonTest.class, URIDistanceTest.class, FragmentationTest.class,
+ AllEditTests.class, CommandStackTestSuite.class, MatchEngineFactoryRegistryTest.class })
public class AllTests {
/**
* Standalone launcher for all of compare's tests.
diff --git a/plugins/org.eclipse.emf.compare.uml2.rcp.ui/src/org/eclipse/emf/compare/uml2/rcp/ui/internal/accessor/UMLStereotypeApplicationChangeFeatureAccessor.java b/plugins/org.eclipse.emf.compare.uml2.rcp.ui/src/org/eclipse/emf/compare/uml2/rcp/ui/internal/accessor/UMLStereotypeApplicationChangeFeatureAccessor.java
index c7d7471f0..c087137d2 100644
--- a/plugins/org.eclipse.emf.compare.uml2.rcp.ui/src/org/eclipse/emf/compare/uml2/rcp/ui/internal/accessor/UMLStereotypeApplicationChangeFeatureAccessor.java
+++ b/plugins/org.eclipse.emf.compare.uml2.rcp.ui/src/org/eclipse/emf/compare/uml2/rcp/ui/internal/accessor/UMLStereotypeApplicationChangeFeatureAccessor.java
@@ -27,9 +27,9 @@ import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.DifferenceKind;
import org.eclipse.emf.compare.DifferenceState;
import org.eclipse.emf.compare.Match;
+import org.eclipse.emf.compare.internal.utils.DiffUtil;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.IMergeViewer.MergeViewerSide;
import org.eclipse.emf.compare.uml2.internal.StereotypeApplicationChange;
-import org.eclipse.emf.compare.utils.DiffUtil;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/AbstractTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/AbstractTest.java
index 2791e82ac..514d085b7 100644
--- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/AbstractTest.java
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/AbstractTest.java
@@ -33,6 +33,7 @@ import org.eclipse.emf.compare.ReferenceChange;
import org.eclipse.emf.compare.merge.BatchMerger;
import org.eclipse.emf.compare.merge.IBatchMerger;
import org.eclipse.emf.compare.merge.IMerger;
+import org.eclipse.emf.compare.postprocessor.IPostProcessor;
import org.eclipse.emf.compare.postprocessor.PostProcessorDescriptorRegistryImpl;
import org.eclipse.emf.compare.scope.DefaultComparisonScope;
import org.eclipse.emf.compare.scope.IComparisonScope;
@@ -54,7 +55,7 @@ public abstract class AbstractTest {
private EMFCompare emfCompare;
- private static final IMerger.Registry mergerRegistry = IMerger.RegistryImpl.createStandaloneInstance();
+ private IMerger.Registry mergerRegistry;
@BeforeClass
public static void fillRegistries() {
@@ -63,19 +64,20 @@ public abstract class AbstractTest {
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("uml", //$NON-NLS-1$
new UMLResourceFactoryImpl());
-
- final IMerger umlMerger = new UMLMerger();
- umlMerger.setRanking(11);
- mergerRegistry.add(umlMerger);
}
@Before
public void before() {
- PostProcessorDescriptorRegistryImpl<String> registry = new PostProcessorDescriptorRegistryImpl<String>();
- registry.put(UMLPostProcessor.class.getName(), new TestPostProcessor.TestPostProcessorDescriptor(
- Pattern.compile("http://www.eclipse.org/uml2/\\d\\.0\\.0/UML"), null, new UMLPostProcessor(),
- 20));
- emfCompare = EMFCompare.builder().setPostProcessorRegistry(registry).build();
+ final IPostProcessor.Descriptor.Registry<String> postProcessorRegistry = new PostProcessorDescriptorRegistryImpl<String>();
+ postProcessorRegistry.put(UMLPostProcessor.class.getName(),
+ new TestPostProcessor.TestPostProcessorDescriptor(Pattern
+ .compile("http://www.eclipse.org/uml2/\\d\\.0\\.0/UML"), null,
+ new UMLPostProcessor(), 20));
+ emfCompare = EMFCompare.builder().setPostProcessorRegistry(postProcessorRegistry).build();
+ mergerRegistry = IMerger.RegistryImpl.createStandaloneInstance();
+ final IMerger umlMerger = new UMLMerger();
+ umlMerger.setRanking(11);
+ mergerRegistry.add(umlMerger);
}
protected EMFCompare getCompare() {
@@ -91,6 +93,10 @@ public abstract class AbstractTest {
return getCompare().compare(scope);
}
+ protected IMerger.Registry getMergerRegistry() {
+ return mergerRegistry;
+ }
+
protected enum TestKind {
ADD, DELETE;
}
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociation2Test.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociation2Test.java
index 48608cd3f..4dc748179 100644
--- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociation2Test.java
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociation2Test.java
@@ -28,6 +28,7 @@ import org.eclipse.emf.compare.uml2.internal.AssociationChange;
import org.eclipse.emf.compare.uml2.tests.AbstractTest;
import org.eclipse.emf.compare.uml2.tests.association.data.AssociationInputData;
import org.eclipse.emf.ecore.resource.Resource;
+import org.junit.Ignore;
import org.junit.Test;
@SuppressWarnings("nls")
@@ -53,6 +54,8 @@ public class AddAssociation2Test extends AbstractTest {
}
@Test
+ @Ignore
+ // FIXME: See Bug 410737
public void testMergeLtRA30UseCase() throws IOException {
final Resource left = input.getA3Left();
final Resource right = input.getA3Right();
@@ -70,6 +73,8 @@ public class AddAssociation2Test extends AbstractTest {
}
@Test
+ @Ignore
+ // FIXME: See Bug 410737
public void testMergeRtLA31UseCase() throws IOException {
final Resource left = input.getA3Left();
final Resource right = input.getA3Right();
@@ -103,10 +108,11 @@ public class AddAssociation2Test extends AbstractTest {
}
@Test
+ @Ignore
+ // FIXME: See Bug 410737
public void testMergeLtRA30UseCase3way() throws IOException {
final Resource left = input.getA3Left();
final Resource right = input.getA3Right();
-
testMergeLeftToRight(left, right, right);
}
@@ -128,6 +134,8 @@ public class AddAssociation2Test extends AbstractTest {
}
@Test
+ @Ignore
+ // FIXME: See Bug 410737
public void testMergeLtRA31UseCase3way() throws IOException {
final Resource left = input.getA3Left();
final Resource right = input.getA3Right();
@@ -138,12 +146,13 @@ public class AddAssociation2Test extends AbstractTest {
private void testAB1(TestKind kind, final Comparison comparison) {
final List<Diff> differences = comparison.getDifferences();
- assertSame(Integer.valueOf(13), Integer.valueOf(differences.size()));
+ assertSame(Integer.valueOf(14), Integer.valueOf(differences.size()));
Predicate<? super Diff> addAssociationDescription = null;
Predicate<? super Diff> addPropertyClass1Description = null;
Predicate<? super Diff> addPropertyClass0Description = null;
Predicate<? super Diff> addPropertyClass0InAssociationDescription = null;
+ Predicate<? super Diff> addPropertyClass1InAssociationDescription = null;
Predicate<? super Diff> addRefAssociationInPropertyClass1Description = null;
Predicate<? super Diff> addRefTypeInPropertyClass1Description = null;
Predicate<? super Diff> addRefAssociationInPropertyClass0Description = null;
@@ -161,6 +170,8 @@ public class AddAssociation2Test extends AbstractTest {
"model.Class1.class0");
addPropertyClass0InAssociationDescription = removedFromReference("model.class1_class0_0",
"memberEnd", "model.Class1.class0");
+ addPropertyClass1InAssociationDescription = removedFromReference("model.class1_class0_0",
+ "memberEnd", "model.class1_class0_0.class1");
addRefAssociationInPropertyClass1Description = changedReference("model.class1_class0_0.class1",
"association", "model.class1_class0_0", null);
addRefTypeInPropertyClass1Description = changedReference("model.class1_class0_0.class1", "type",
@@ -181,6 +192,8 @@ public class AddAssociation2Test extends AbstractTest {
"model.Class1.class0");
addPropertyClass0InAssociationDescription = addedToReference("model.class1_class0_0",
"memberEnd", "model.Class1.class0");
+ addPropertyClass1InAssociationDescription = addedToReference("model.class1_class0_0",
+ "memberEnd", "model.class1_class0_0.class1");
addRefAssociationInPropertyClass1Description = changedReference("model.class1_class0_0.class1",
"association", null, "model.class1_class0_0");
addRefTypeInPropertyClass1Description = changedReference("model.class1_class0_0.class1", "type",
@@ -200,6 +213,8 @@ public class AddAssociation2Test extends AbstractTest {
final Diff addPropertyClass0 = Iterators.find(differences.iterator(), addPropertyClass0Description);
final Diff addPropertyClass0InAssociation = Iterators.find(differences.iterator(),
addPropertyClass0InAssociationDescription);
+ final Diff addPropertyClass1InAssociation = Iterators.find(differences.iterator(),
+ addPropertyClass1InAssociationDescription);
final Diff addRefAssociationInPropertyClass1 = Iterators.find(differences.iterator(),
addRefAssociationInPropertyClass1Description);
final Diff addRefTypeInPropertyClass1 = Iterators.find(differences.iterator(),
@@ -216,12 +231,12 @@ public class AddAssociation2Test extends AbstractTest {
addLiteralIntegerInClass0Description);
final Diff addUnlimitedNaturalInClass0 = Iterators.find(differences.iterator(),
addUnlimitedNaturalInClass0Description);
- // duplicate diff: add Association.memberEnd to class1s
assertNotNull(addAssociation);
assertNotNull(addPropertyClass1);
assertNotNull(addPropertyClass0);
assertNotNull(addPropertyClass0InAssociation);
+ assertNotNull(addPropertyClass1InAssociation);
assertNotNull(addRefAssociationInPropertyClass1);
assertNotNull(addRefTypeInPropertyClass1);
assertNotNull(addRefAssociationInPropertyClass0);
@@ -242,12 +257,13 @@ public class AddAssociation2Test extends AbstractTest {
instanceOf(AssociationChange.class), ofKind(DifferenceKind.DELETE)));
}
assertNotNull(addUMLAssociation);
- assertSame(Integer.valueOf(12), Integer.valueOf(addUMLAssociation.getRefinedBy().size()));
+ assertSame(Integer.valueOf(13), Integer.valueOf(addUMLAssociation.getRefinedBy().size()));
assertTrue(addUMLAssociation.getRefinedBy().contains(addAssociation));
assertTrue(addUMLAssociation.getRefinedBy().contains(addPropertyClass1));
assertTrue(addUMLAssociation.getRefinedBy().contains(addPropertyClass0));
assertTrue(addUMLAssociation.getRefinedBy().contains(addPropertyClass0InAssociation));
+ assertTrue(addUMLAssociation.getRefinedBy().contains(addPropertyClass1InAssociation));
assertTrue(addUMLAssociation.getRefinedBy().contains(addRefAssociationInPropertyClass1));
assertTrue(addUMLAssociation.getRefinedBy().contains(addRefTypeInPropertyClass1));
assertTrue(addUMLAssociation.getRefinedBy().contains(addRefAssociationInPropertyClass0));
@@ -256,7 +272,6 @@ public class AddAssociation2Test extends AbstractTest {
assertTrue(addUMLAssociation.getRefinedBy().contains(addUnlimitedNaturalInClass1));
assertTrue(addUMLAssociation.getRefinedBy().contains(addLiteralIntegerInClass0));
assertTrue(addUMLAssociation.getRefinedBy().contains(addUnlimitedNaturalInClass0));
- // duplicate diff: add Association.memberEnd to class1s
// CHECK REQUIREMENT
if (kind.equals(TestKind.ADD)) {
@@ -301,12 +316,12 @@ public class AddAssociation2Test extends AbstractTest {
assertSame(Integer.valueOf(1), Integer.valueOf(addUnlimitedNaturalInClass0.getRequires().size()));
assertTrue(addUnlimitedNaturalInClass0.getRequires().contains(addPropertyClass0));
} else {
- assertSame(Integer.valueOf(4), Integer.valueOf(addPropertyClass1.getRequires().size()));
+ assertSame(Integer.valueOf(5), Integer.valueOf(addPropertyClass1.getRequires().size()));
assertTrue(addPropertyClass1.getRequires().contains(addLiteralIntegerInClass1));
assertTrue(addPropertyClass1.getRequires().contains(addUnlimitedNaturalInClass1));
assertTrue(addPropertyClass1.getRequires().contains(addRefAssociationInPropertyClass1));
assertTrue(addPropertyClass1.getRequires().contains(addRefTypeInPropertyClass1));
- // duplicate diff: add Association.memberEnd to class1s
+ assertTrue(addPropertyClass1.getRequires().contains(addPropertyClass1InAssociation));
assertSame(Integer.valueOf(5), Integer.valueOf(addPropertyClass0.getRequires().size()));
assertTrue(addPropertyClass0.getRequires().contains(addLiteralIntegerInClass0));
@@ -322,12 +337,12 @@ public class AddAssociation2Test extends AbstractTest {
.size()));
assertSame(Integer.valueOf(0), Integer.valueOf(addRefTypeInPropertyClass0.getRequires().size()));
- assertSame(Integer.valueOf(4), Integer.valueOf(addAssociation.getRequires().size()));
+ assertSame(Integer.valueOf(5), Integer.valueOf(addAssociation.getRequires().size()));
assertTrue(addAssociation.getRequires().contains(addPropertyClass1));
assertTrue(addAssociation.getRequires().contains(addRefAssociationInPropertyClass1));
assertTrue(addAssociation.getRequires().contains(addRefAssociationInPropertyClass0));
- assertTrue(addPropertyClass0.getRequires().contains(addPropertyClass0InAssociation));
- // duplicate diff: add Association.memberEnd to class1s
+ assertTrue(addAssociation.getRequires().contains(addPropertyClass0InAssociation));
+ assertTrue(addAssociation.getRequires().contains(addPropertyClass1InAssociation));
assertSame(Integer.valueOf(0), Integer.valueOf(addUMLAssociation.getRequires().size()));
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociation3Test.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociation3Test.java
index 9bb96f65b..078f14e6d 100644
--- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociation3Test.java
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociation3Test.java
@@ -138,13 +138,13 @@ public class AddAssociation3Test extends AbstractTest {
private void testAB1(TestKind kind, final Comparison comparison) {
final List<Diff> differences = comparison.getDifferences();
- assertSame(Integer.valueOf(13), Integer.valueOf(differences.size()));
+ assertSame(Integer.valueOf(14), Integer.valueOf(differences.size()));
Predicate<? super Diff> addAssociationDescription = null;
Predicate<? super Diff> addPropertyClass1Description = null;
Predicate<? super Diff> addPropertyClass0Description = null;
Predicate<? super Diff> addPropertyClass1InAssociationDescription = null;
- // duplicate diff: Association.memberEnd to class0
+ Predicate<? super Diff> addPropertyClass0InAssociationDescription = null;
Predicate<? super Diff> addRefAssociationInPropertyClass1Description = null;
Predicate<? super Diff> addRefTypeInPropertyClass1Description = null;
Predicate<? super Diff> addRefAssociationInPropertyClass0Description = null;
@@ -162,6 +162,8 @@ public class AddAssociation3Test extends AbstractTest {
"model.AssociationClass0.class0");
addPropertyClass1InAssociationDescription = removedFromReference("model.AssociationClass0",
"memberEnd", "model.Class0.class1");
+ addPropertyClass0InAssociationDescription = removedFromReference("model.AssociationClass0",
+ "memberEnd", "model.AssociationClass0.class0");
addRefAssociationInPropertyClass1Description = changedReference("model.Class0.class1",
"association", "model.AssociationClass0", null);
addRefTypeInPropertyClass1Description = changedReference("model.Class0.class1", "type",
@@ -182,6 +184,8 @@ public class AddAssociation3Test extends AbstractTest {
"model.AssociationClass0.class0");
addPropertyClass1InAssociationDescription = addedToReference("model.AssociationClass0",
"memberEnd", "model.Class0.class1");
+ addPropertyClass0InAssociationDescription = addedToReference("model.AssociationClass0",
+ "memberEnd", "model.AssociationClass0.class0");
addRefAssociationInPropertyClass1Description = changedReference("model.Class0.class1",
"association", null, "model.AssociationClass0");
addRefTypeInPropertyClass1Description = changedReference("model.Class0.class1", "type", null,
@@ -201,6 +205,8 @@ public class AddAssociation3Test extends AbstractTest {
final Diff addPropertyClass0 = Iterators.find(differences.iterator(), addPropertyClass0Description);
final Diff addPropertyClass1InAssociation = Iterators.find(differences.iterator(),
addPropertyClass1InAssociationDescription);
+ final Diff addPropertyClass0InAssociation = Iterators.find(differences.iterator(),
+ addPropertyClass0InAssociationDescription);
final Diff addRefAssociationInPropertyClass1 = Iterators.find(differences.iterator(),
addRefAssociationInPropertyClass1Description);
final Diff addRefTypeInPropertyClass1 = Iterators.find(differences.iterator(),
@@ -231,6 +237,7 @@ public class AddAssociation3Test extends AbstractTest {
assertNotNull(addUnlimitedNaturalInClass1);
assertNotNull(addLiteralIntegerInClass0);
assertNotNull(addUnlimitedNaturalInClass0);
+ assertNotNull(addPropertyClass0InAssociation);
// CHECK EXTENSION
assertSame(Integer.valueOf(1), count(differences, instanceOf(AssociationChange.class)));
@@ -243,7 +250,7 @@ public class AddAssociation3Test extends AbstractTest {
instanceOf(AssociationChange.class), ofKind(DifferenceKind.DELETE)));
}
assertNotNull(addUMLAssociation);
- assertSame(Integer.valueOf(12), Integer.valueOf(addUMLAssociation.getRefinedBy().size()));
+ assertSame(Integer.valueOf(13), Integer.valueOf(addUMLAssociation.getRefinedBy().size()));
assertTrue(addUMLAssociation.getRefinedBy().contains(addRefTypeInPropertyClass1));
assertTrue(addUMLAssociation.getRefinedBy().contains(addLiteralIntegerInClass1));
assertTrue(addUMLAssociation.getRefinedBy().contains(addUnlimitedNaturalInClass1));
@@ -256,7 +263,7 @@ public class AddAssociation3Test extends AbstractTest {
assertTrue(addUMLAssociation.getRefinedBy().contains(addPropertyClass0));
assertTrue(addUMLAssociation.getRefinedBy().contains(addPropertyClass1));
assertTrue(addUMLAssociation.getRefinedBy().contains(addPropertyClass1InAssociation));
- // duplicate diff: Association.memberEnd to class0
+ assertTrue(addUMLAssociation.getRefinedBy().contains(addPropertyClass0InAssociation));
// CHECK REQUIREMENT
if (kind.equals(TestKind.ADD)) {
@@ -308,12 +315,12 @@ public class AddAssociation3Test extends AbstractTest {
assertTrue(addPropertyClass1.getRequires().contains(addRefTypeInPropertyClass1));
assertTrue(addPropertyClass1.getRequires().contains(addPropertyClass1InAssociation));
- assertSame(Integer.valueOf(4), Integer.valueOf(addPropertyClass0.getRequires().size()));
+ assertSame(Integer.valueOf(5), Integer.valueOf(addPropertyClass0.getRequires().size()));
assertTrue(addPropertyClass0.getRequires().contains(addLiteralIntegerInClass0));
assertTrue(addPropertyClass0.getRequires().contains(addUnlimitedNaturalInClass0));
assertTrue(addPropertyClass0.getRequires().contains(addRefAssociationInPropertyClass0));
assertTrue(addPropertyClass0.getRequires().contains(addRefTypeInPropertyClass0));
- // duplicate diff: Association.memberEnd to class0
+ assertTrue(addPropertyClass0.getRequires().contains(addPropertyClass0InAssociation));
assertSame(Integer.valueOf(0), Integer.valueOf(addRefAssociationInPropertyClass1.getRequires()
.size()));
@@ -322,12 +329,12 @@ public class AddAssociation3Test extends AbstractTest {
.size()));
assertSame(Integer.valueOf(0), Integer.valueOf(addRefTypeInPropertyClass0.getRequires().size()));
- assertSame(Integer.valueOf(4), Integer.valueOf(addAssociation.getRequires().size()));
+ assertSame(Integer.valueOf(5), Integer.valueOf(addAssociation.getRequires().size()));
assertTrue(addAssociation.getRequires().contains(addPropertyClass0));
assertTrue(addAssociation.getRequires().contains(addRefAssociationInPropertyClass1));
assertTrue(addAssociation.getRequires().contains(addRefAssociationInPropertyClass0));
assertTrue(addAssociation.getRequires().contains(addPropertyClass1InAssociation));
- // duplicate diff: Association.memberEnd to class0
+ assertTrue(addAssociation.getRequires().contains(addPropertyClass0InAssociation));
assertSame(Integer.valueOf(0), Integer.valueOf(addUMLAssociation.getRequires().size()));
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociationTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociationTest.java
index 12b001d0b..5e2aa873e 100644
--- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociationTest.java
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociationTest.java
@@ -28,7 +28,6 @@ import org.eclipse.emf.compare.uml2.internal.AssociationChange;
import org.eclipse.emf.compare.uml2.tests.AbstractTest;
import org.eclipse.emf.compare.uml2.tests.association.data.AssociationInputData;
import org.eclipse.emf.ecore.resource.Resource;
-import org.junit.Ignore;
import org.junit.Test;
@SuppressWarnings("nls")
@@ -54,8 +53,6 @@ public class AddAssociationTest extends AbstractTest {
}
@Test
- @Ignore
- // See UMLPostProcessor#removeDuplicateDiffs(Comparison)
public void testMergeLtRA10UseCase() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Right();
@@ -73,8 +70,6 @@ public class AddAssociationTest extends AbstractTest {
}
@Test
- @Ignore
- // See UMLPostProcessor#removeDuplicateDiffs(Comparison)
public void testMergeRtLA11UseCase() throws IOException {
final Resource left = input.getA1Right();
final Resource right = input.getA1Left();
@@ -108,8 +103,6 @@ public class AddAssociationTest extends AbstractTest {
}
@Test
- @Ignore
- // See UMLPostProcessor#removeDuplicateDiffs(Comparison)
public void testMergeLtRA10UseCase3way() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Right();
@@ -135,8 +128,6 @@ public class AddAssociationTest extends AbstractTest {
}
@Test
- @Ignore
- // See UMLPostProcessor#removeDuplicateDiffs(Comparison)
public void testMergeLtRA11UseCase3way() throws IOException {
final Resource left = input.getA1Left();
final Resource right = input.getA1Right();
@@ -148,7 +139,7 @@ public class AddAssociationTest extends AbstractTest {
final List<Diff> differences = comparison.getDifferences();
// We should have no less and no more than 16 differences
- assertSame(Integer.valueOf(12), Integer.valueOf(differences.size()));
+ assertSame(Integer.valueOf(16), Integer.valueOf(differences.size()));
Predicate<? super Diff> addAssociationDescription = null;
Predicate<? super Diff> addNavigableOwnedEndClass1InAssociationDescription = null;
@@ -161,11 +152,10 @@ public class AddAssociationTest extends AbstractTest {
Predicate<? super Diff> addUnlimitedNaturalInClass1Description = null;
Predicate<? super Diff> addLiteralIntegerInClass2Description = null;
Predicate<? super Diff> addUnlimitedNaturalInClass2Description = null;
- // duplicate diffs: Add differences on (opposite and subset features):
- // - Association.memberEnd to class1s
- // - Association.memberEnd to class2s
- // - Association.ownedEnd to class1s
- // - Association.ownedEnd to class2s
+ Predicate<? super Diff> addMemberEndClass1InAssociationDescription = null;
+ Predicate<? super Diff> addMemberEndClass2InAssociationDescription = null;
+ Predicate<? super Diff> addOwnedEndClass1Description = null;
+ Predicate<? super Diff> addOwnedEndClass2Description = null;
if (kind.equals(TestKind.DELETE)) {
addAssociationDescription = removed("myModel.class1sToClass2s"); //$NON-NLS-1$
@@ -185,6 +175,14 @@ public class AddAssociationTest extends AbstractTest {
addUnlimitedNaturalInClass1Description = removedUpperValueIn("myModel.class1sToClass2s.class1s");
addLiteralIntegerInClass2Description = removedLowerValueIn("myModel.class1sToClass2s.class2s");
addUnlimitedNaturalInClass2Description = removedUpperValueIn("myModel.class1sToClass2s.class2s");
+ addMemberEndClass1InAssociationDescription = removedFromReference("myModel.class1sToClass2s",
+ "memberEnd", "myModel.class1sToClass2s.class1s");
+ addMemberEndClass2InAssociationDescription = removedFromReference("myModel.class1sToClass2s",
+ "memberEnd", "myModel.class1sToClass2s.class2s");
+ addOwnedEndClass1Description = removedFromReference("myModel.class1sToClass2s", "ownedEnd",
+ "myModel.class1sToClass2s.class1s");
+ addOwnedEndClass2Description = removedFromReference("myModel.class1sToClass2s", "ownedEnd",
+ "myModel.class1sToClass2s.class2s");
} else {
addAssociationDescription = added("myModel.class1sToClass2s"); //$NON-NLS-1$
addNavigableOwnedEndClass1InAssociationDescription = addedToReference("myModel.class1sToClass2s",
@@ -203,6 +201,14 @@ public class AddAssociationTest extends AbstractTest {
addUnlimitedNaturalInClass1Description = addedUpperValueIn("myModel.class1sToClass2s.class1s");
addLiteralIntegerInClass2Description = addedLowerValueIn("myModel.class1sToClass2s.class2s");
addUnlimitedNaturalInClass2Description = addedUpperValueIn("myModel.class1sToClass2s.class2s");
+ addMemberEndClass1InAssociationDescription = addedToReference("myModel.class1sToClass2s",
+ "memberEnd", "myModel.class1sToClass2s.class1s");
+ addMemberEndClass2InAssociationDescription = addedToReference("myModel.class1sToClass2s",
+ "memberEnd", "myModel.class1sToClass2s.class2s");
+ addOwnedEndClass1Description = addedToReference("myModel.class1sToClass2s", "ownedEnd",
+ "myModel.class1sToClass2s.class1s");
+ addOwnedEndClass2Description = addedToReference("myModel.class1sToClass2s", "ownedEnd",
+ "myModel.class1sToClass2s.class2s");
}
final Diff addAssociation = Iterators.find(differences.iterator(), addAssociationDescription);
@@ -226,6 +232,14 @@ public class AddAssociationTest extends AbstractTest {
addLiteralIntegerInClass2Description);
final Diff addUnlimitedNaturalInClass2 = Iterators.find(differences.iterator(),
addUnlimitedNaturalInClass2Description);
+ final Diff addMemberEndClass1InAssociation = Iterators.find(differences.iterator(),
+ addMemberEndClass1InAssociationDescription);
+ final Diff addMemberEndClass2InAssociation = Iterators.find(differences.iterator(),
+ addMemberEndClass2InAssociationDescription);
+ final Diff addOwnedEndClass1InAssociation = Iterators.find(differences.iterator(),
+ addOwnedEndClass1Description);
+ final Diff addOwnedEndClass2InAssociation = Iterators.find(differences.iterator(),
+ addOwnedEndClass2Description);
assertNotNull(addNavigableOwnedEndClass1InAssociation);
assertNotNull(addNavigableOwnedEndClass2InAssociation);
@@ -238,6 +252,10 @@ public class AddAssociationTest extends AbstractTest {
assertNotNull(addUnlimitedNaturalInClass1);
assertNotNull(addLiteralIntegerInClass2);
assertNotNull(addUnlimitedNaturalInClass2);
+ assertNotNull(addMemberEndClass1InAssociation);
+ assertNotNull(addMemberEndClass2InAssociation);
+ assertNotNull(addOwnedEndClass1InAssociation);
+ assertNotNull(addOwnedEndClass2InAssociation);
// CHECK EXTENSION
assertSame(Integer.valueOf(1), count(differences, instanceOf(AssociationChange.class)));
@@ -250,7 +268,7 @@ public class AddAssociationTest extends AbstractTest {
instanceOf(AssociationChange.class), ofKind(DifferenceKind.DELETE)));
}
assertNotNull(addUMLAssociation);
- assertSame(Integer.valueOf(11), Integer.valueOf(addUMLAssociation.getRefinedBy().size()));
+ assertSame(Integer.valueOf(15), Integer.valueOf(addUMLAssociation.getRefinedBy().size()));
assertTrue(addUMLAssociation.getRefinedBy().contains(addAssociation));
assertTrue(addUMLAssociation.getRefinedBy().contains(addNavigableOwnedEndClass1InAssociation));
assertTrue(addUMLAssociation.getRefinedBy().contains(addNavigableOwnedEndClass2InAssociation));
@@ -262,89 +280,63 @@ public class AddAssociationTest extends AbstractTest {
assertTrue(addUMLAssociation.getRefinedBy().contains(addUnlimitedNaturalInClass1));
assertTrue(addUMLAssociation.getRefinedBy().contains(addLiteralIntegerInClass2));
assertTrue(addUMLAssociation.getRefinedBy().contains(addUnlimitedNaturalInClass2));
+ assertTrue(addUMLAssociation.getRefinedBy().contains(addMemberEndClass1InAssociation));
+ assertTrue(addUMLAssociation.getRefinedBy().contains(addMemberEndClass2InAssociation));
+ assertTrue(addUMLAssociation.getRefinedBy().contains(addOwnedEndClass1InAssociation));
+ assertTrue(addUMLAssociation.getRefinedBy().contains(addOwnedEndClass2InAssociation));
// CHECK REQUIREMENT
if (kind.equals(TestKind.ADD)) {
assertSame(Integer.valueOf(2), Integer.valueOf(addRefAssociationInPropertyClass1.getRequires()
.size()));
assertTrue(addRefAssociationInPropertyClass1.getRequires().contains(
- addNavigableOwnedEndClass1InAssociation));
- // duplicate diff: requires Association.ownedEnd to class1s
+ addOwnedEndClass1InAssociation));
assertTrue(addRefAssociationInPropertyClass1.getRequires().contains(addAssociation));
assertSame(Integer.valueOf(1), Integer.valueOf(addRefTypeInPropertyClass1.getRequires().size()));
- assertTrue(addRefTypeInPropertyClass1.getRequires().contains(
- addNavigableOwnedEndClass1InAssociation));
- // duplicate diff: requires Association.ownedEnd to class1s
+ assertTrue(addRefTypeInPropertyClass1.getRequires().contains(addOwnedEndClass1InAssociation));
assertSame(Integer.valueOf(2), Integer.valueOf(addRefAssociationInPropertyClass2.getRequires()
.size()));
assertTrue(addRefAssociationInPropertyClass2.getRequires().contains(
- addNavigableOwnedEndClass2InAssociation));
- // duplicate diff: requires Association.ownedEnd to class2s
+ addOwnedEndClass2InAssociation));
assertTrue(addRefAssociationInPropertyClass2.getRequires().contains(addAssociation));
assertSame(Integer.valueOf(1), Integer.valueOf(addRefTypeInPropertyClass2.getRequires().size()));
- assertTrue(addRefTypeInPropertyClass2.getRequires().contains(
- addNavigableOwnedEndClass2InAssociation));
- // duplicate diff: requires Association.ownedEnd to class2s
+ assertTrue(addRefTypeInPropertyClass2.getRequires().contains(addOwnedEndClass2InAssociation));
assertSame(Integer.valueOf(0), Integer.valueOf(addAssociation.getRequires().size()));
assertSame(Integer.valueOf(0), Integer.valueOf(addUMLAssociation.getRequires().size()));
- assertSame(Integer.valueOf(1), Integer.valueOf(addNavigableOwnedEndClass1InAssociation
+ assertSame(Integer.valueOf(2), Integer.valueOf(addNavigableOwnedEndClass1InAssociation
.getRequires().size()));
assertTrue(addNavigableOwnedEndClass1InAssociation.getRequires().contains(addAssociation));
- // duplicate diff: requires Association.ownedEnd to class1s
+ assertTrue(addNavigableOwnedEndClass1InAssociation.getRequires().contains(
+ addOwnedEndClass1InAssociation));
- assertSame(Integer.valueOf(1), Integer.valueOf(addNavigableOwnedEndClass2InAssociation
+ assertSame(Integer.valueOf(2), Integer.valueOf(addNavigableOwnedEndClass2InAssociation
.getRequires().size()));
assertTrue(addNavigableOwnedEndClass2InAssociation.getRequires().contains(addAssociation));
- // duplicate diff: requires Association.ownedEnd to class2s
+ assertTrue(addNavigableOwnedEndClass2InAssociation.getRequires().contains(
+ addOwnedEndClass2InAssociation));
assertSame(Integer.valueOf(1), Integer.valueOf(addLiteralIntegerInClass1.getRequires().size()));
- assertTrue(addLiteralIntegerInClass1.getRequires().contains(
- addNavigableOwnedEndClass1InAssociation));
- // duplicate diff: requires Association.ownedEnd to class1s
+ assertTrue(addLiteralIntegerInClass1.getRequires().contains(addOwnedEndClass1InAssociation));
assertSame(Integer.valueOf(1), Integer.valueOf(addUnlimitedNaturalInClass1.getRequires().size()));
- assertTrue(addUnlimitedNaturalInClass1.getRequires().contains(
- addNavigableOwnedEndClass1InAssociation));
- // duplicate diff: requires Association.ownedEnd to class1s
+ assertTrue(addUnlimitedNaturalInClass1.getRequires().contains(addOwnedEndClass1InAssociation));
assertSame(Integer.valueOf(1), Integer.valueOf(addLiteralIntegerInClass2.getRequires().size()));
- assertTrue(addLiteralIntegerInClass2.getRequires().contains(
- addNavigableOwnedEndClass2InAssociation));
- // duplicate diff: requires Association.ownedEnd to class2s
+ assertTrue(addLiteralIntegerInClass2.getRequires().contains(addOwnedEndClass2InAssociation));
assertSame(Integer.valueOf(1), Integer.valueOf(addUnlimitedNaturalInClass2.getRequires().size()));
- assertTrue(addUnlimitedNaturalInClass2.getRequires().contains(
- addNavigableOwnedEndClass2InAssociation));
- // duplicate diff: requires Association.ownedEnd to class2s
+ assertTrue(addUnlimitedNaturalInClass2.getRequires().contains(addOwnedEndClass2InAssociation));
} else {
- assertSame(Integer.valueOf(4), Integer.valueOf(addNavigableOwnedEndClass1InAssociation
+ assertSame(Integer.valueOf(0), Integer.valueOf(addNavigableOwnedEndClass1InAssociation
.getRequires().size()));
- // duplicate diff
- assertTrue(addNavigableOwnedEndClass1InAssociation.getRequires().contains(
- addLiteralIntegerInClass1));
- assertTrue(addNavigableOwnedEndClass1InAssociation.getRequires().contains(
- addUnlimitedNaturalInClass1));
- assertTrue(addNavigableOwnedEndClass1InAssociation.getRequires().contains(
- addRefAssociationInPropertyClass1));
- assertTrue(addNavigableOwnedEndClass1InAssociation.getRequires().contains(
- addRefTypeInPropertyClass1));
- assertSame(Integer.valueOf(4), Integer.valueOf(addNavigableOwnedEndClass2InAssociation
+ assertSame(Integer.valueOf(0), Integer.valueOf(addNavigableOwnedEndClass2InAssociation
.getRequires().size()));
- // duplicate diff
- assertTrue(addNavigableOwnedEndClass2InAssociation.getRequires().contains(
- addLiteralIntegerInClass2));
- assertTrue(addNavigableOwnedEndClass2InAssociation.getRequires().contains(
- addUnlimitedNaturalInClass2));
- assertTrue(addNavigableOwnedEndClass2InAssociation.getRequires().contains(
- addRefAssociationInPropertyClass2));
- assertTrue(addNavigableOwnedEndClass2InAssociation.getRequires().contains(
- addRefTypeInPropertyClass2));
assertSame(Integer.valueOf(0), Integer.valueOf(addRefAssociationInPropertyClass1.getRequires()
.size()));
@@ -353,16 +345,15 @@ public class AddAssociationTest extends AbstractTest {
.size()));
assertSame(Integer.valueOf(0), Integer.valueOf(addRefTypeInPropertyClass2.getRequires().size()));
- assertSame(Integer.valueOf(4), Integer.valueOf(addAssociation.getRequires().size()));
+ assertSame(Integer.valueOf(8), Integer.valueOf(addAssociation.getRequires().size()));
assertTrue(addAssociation.getRequires().contains(addNavigableOwnedEndClass1InAssociation));
assertTrue(addAssociation.getRequires().contains(addNavigableOwnedEndClass2InAssociation));
assertTrue(addAssociation.getRequires().contains(addRefAssociationInPropertyClass1));
assertTrue(addAssociation.getRequires().contains(addRefAssociationInPropertyClass2));
- // duplicate diff: requires:
- // - Association.memberEnd to class1s
- // - Association.memberEnd to class2s
- // - Association.ownedEnd to class1s
- // - Association.ownedEnd to class2s
+ assertTrue(addAssociation.getRequires().contains(addOwnedEndClass1InAssociation));
+ assertTrue(addAssociation.getRequires().contains(addOwnedEndClass2InAssociation));
+ assertTrue(addAssociation.getRequires().contains(addMemberEndClass1InAssociation));
+ assertTrue(addAssociation.getRequires().contains(addMemberEndClass2InAssociation));
assertSame(Integer.valueOf(0), Integer.valueOf(addUMLAssociation.getRequires().size()));
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/ChangeAssociationTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/ChangeAssociationTest.java
index 45b1e1bc0..c608a1d58 100644
--- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/ChangeAssociationTest.java
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/ChangeAssociationTest.java
@@ -138,14 +138,14 @@ public class ChangeAssociationTest extends AbstractTest {
final List<Diff> differences = comparison.getDifferences();
// We should have no less and no more than 5 differences
- assertSame(Integer.valueOf(5), Integer.valueOf(differences.size()));
+ assertSame(Integer.valueOf(6), Integer.valueOf(differences.size()));
Predicate<? super Diff> addPropertyClass2Description = null;
Predicate<? super Diff> addRefAssociationInPropertyClass2Description = null;
Predicate<? super Diff> addRefTypeInPropertyClass2Description = null;
Predicate<? super Diff> addLiteralIntegerInClass2Description = null;
Predicate<? super Diff> addUnlimitedNaturalInClass2Description = null;
- // duplicate diff: Association.memberEnd to Class2
+ Predicate<? super Diff> addPropertyClass2InAssociationDescription = null;
if (kind.equals(TestKind.DELETE)) {
addPropertyClass2Description = removedFromReference("model.class1_class0_0", "ownedEnd",
@@ -156,6 +156,8 @@ public class ChangeAssociationTest extends AbstractTest {
"model.Class2", null);
addLiteralIntegerInClass2Description = removedLowerValueIn("model.class1_class0_0.Class2");
addUnlimitedNaturalInClass2Description = removedUpperValueIn("model.class1_class0_0.Class2");
+ addPropertyClass2InAssociationDescription = removedFromReference("model.class1_class0_0",
+ "memberEnd", "model.class1_class0_0.Class2");
} else {
addPropertyClass2Description = addedToReference("model.class1_class0_0", "ownedEnd",
"model.class1_class0_0.Class2");
@@ -165,6 +167,8 @@ public class ChangeAssociationTest extends AbstractTest {
null, "model.Class2");
addLiteralIntegerInClass2Description = addedLowerValueIn("model.class1_class0_0.Class2");
addUnlimitedNaturalInClass2Description = addedUpperValueIn("model.class1_class0_0.Class2");
+ addPropertyClass2InAssociationDescription = addedToReference("model.class1_class0_0",
+ "memberEnd", "model.class1_class0_0.Class2");
}
final Diff addPropertyClass2 = Iterators.find(differences.iterator(), addPropertyClass2Description);
@@ -176,12 +180,15 @@ public class ChangeAssociationTest extends AbstractTest {
addLiteralIntegerInClass2Description);
final Diff addUnlimitedNaturalInClass2 = Iterators.find(differences.iterator(),
addUnlimitedNaturalInClass2Description);
+ final Diff addPropertyClass2InAssociation = Iterators.find(differences.iterator(),
+ addPropertyClass2InAssociationDescription);
assertNotNull(addPropertyClass2);
assertNotNull(addRefAssociationInPropertyClass2);
assertNotNull(addRefTypeInPropertyClass2);
assertNotNull(addLiteralIntegerInClass2);
assertNotNull(addUnlimitedNaturalInClass2);
+ assertNotNull(addPropertyClass2InAssociation);
// CHECK EXTENSION
// No extension anymore
@@ -196,7 +203,6 @@ public class ChangeAssociationTest extends AbstractTest {
// assertTrue(changeUMLAssociation.getRefinedBy().contains(addUnlimitedNaturalInClass2));
// assertTrue(changeUMLAssociation.getRefinedBy().contains(addRefAssociationInPropertyClass2));
// assertTrue(changeUMLAssociation.getRefinedBy().contains(addPropertyClass2));
- // duplicate diff: Association.memberEnd to Class2
// CHECK REQUIREMENT
if (kind.equals(TestKind.ADD)) {
@@ -217,12 +223,12 @@ public class ChangeAssociationTest extends AbstractTest {
assertSame(Integer.valueOf(1), Integer.valueOf(addUnlimitedNaturalInClass2.getRequires().size()));
assertTrue(addUnlimitedNaturalInClass2.getRequires().contains(addPropertyClass2));
} else {
- assertSame(Integer.valueOf(4), Integer.valueOf(addPropertyClass2.getRequires().size()));
+ assertSame(Integer.valueOf(5), Integer.valueOf(addPropertyClass2.getRequires().size()));
assertTrue(addPropertyClass2.getRequires().contains(addLiteralIntegerInClass2));
assertTrue(addPropertyClass2.getRequires().contains(addUnlimitedNaturalInClass2));
assertTrue(addPropertyClass2.getRequires().contains(addRefAssociationInPropertyClass2));
assertTrue(addPropertyClass2.getRequires().contains(addRefTypeInPropertyClass2));
- // duplicate diff: Association.memberEnd to Class2
+ assertTrue(addPropertyClass2.getRequires().contains(addPropertyClass2InAssociation));
assertSame(Integer.valueOf(0), Integer.valueOf(addRefAssociationInPropertyClass2.getRequires()
.size()));
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/dependency/AddInterfaceRealizationTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/dependency/AddInterfaceRealizationTest.java
index d017da1ee..c00f08ce4 100644
--- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/dependency/AddInterfaceRealizationTest.java
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/dependency/AddInterfaceRealizationTest.java
@@ -83,12 +83,13 @@ public class AddInterfaceRealizationTest extends AbstractTest {
final List<Diff> differences = comparison.getDifferences();
// We should have no less and no more than 6 differences
- assertSame(Integer.valueOf(5), Integer.valueOf(differences.size()));
+ assertSame(Integer.valueOf(6), Integer.valueOf(differences.size()));
Predicate<? super Diff> addInterfaceRealizationDescription = null;
Predicate<? super Diff> addClientInInterfaceRealizationDescription = null;
Predicate<? super Diff> addSupplierInInterfaceRealizationDescription = null;
Predicate<? super Diff> addContractInInterfaceRealizationDescription = null;
+ Predicate<? super Diff> addClientDependencyInClass0Description = null;
if (kind.equals(TestKind.DELETE)) {
//addInterfaceRealizationDescription = removed("model.Class0.InterfaceRealization0"); //$NON-NLS-1$
@@ -100,6 +101,8 @@ public class AddInterfaceRealizationTest extends AbstractTest {
"model.Class0.InterfaceRealization0", "supplier", "model.Interface0");
addContractInInterfaceRealizationDescription = changedReference(
"model.Class0.InterfaceRealization0", "contract", "model.Interface0", null);
+ addClientDependencyInClass0Description = removedFromReference("model.Class0", "clientDependency",
+ "model.Class0.InterfaceRealization0");
} else {
//addInterfaceRealizationDescription = added("model.Class0.InterfaceRealization0"); //$NON-NLS-1$
addInterfaceRealizationDescription = addedToReference(
@@ -110,6 +113,8 @@ public class AddInterfaceRealizationTest extends AbstractTest {
"model.Class0.InterfaceRealization0", "supplier", "model.Interface0");
addContractInInterfaceRealizationDescription = changedReference(
"model.Class0.InterfaceRealization0", "contract", null, "model.Interface0");
+ addClientDependencyInClass0Description = addedToReference("model.Class0", "clientDependency",
+ "model.Class0.InterfaceRealization0");
}
final Diff addInterfaceRealization = Iterators.find(differences.iterator(),
@@ -120,12 +125,14 @@ public class AddInterfaceRealizationTest extends AbstractTest {
addSupplierInInterfaceRealizationDescription);
final Diff addContractInInterfaceRealization = Iterators.find(differences.iterator(),
addContractInInterfaceRealizationDescription);
- // duplicate diff: NamedElement.clientDependency to InterfaceRealization0
+ final Diff addClientDependencyInClass0 = Iterators.find(differences.iterator(),
+ addClientDependencyInClass0Description);
assertNotNull(addInterfaceRealization);
assertNotNull(addClientInInterfaceRealization);
assertNotNull(addSupplierInInterfaceRealization);
assertNotNull(addContractInInterfaceRealization);
+ assertNotNull(addClientDependencyInClass0);
// CHECK EXTENSION
assertSame(Integer.valueOf(1), count(differences, instanceOf(InterfaceRealizationChange.class)));
@@ -138,12 +145,12 @@ public class AddInterfaceRealizationTest extends AbstractTest {
instanceOf(InterfaceRealizationChange.class), ofKind(DifferenceKind.DELETE)));
}
assertNotNull(addUMLDependency);
- assertSame(Integer.valueOf(4), Integer.valueOf(addUMLDependency.getRefinedBy().size()));
+ assertSame(Integer.valueOf(5), Integer.valueOf(addUMLDependency.getRefinedBy().size()));
assertTrue(addUMLDependency.getRefinedBy().contains(addInterfaceRealization));
assertTrue(addUMLDependency.getRefinedBy().contains(addClientInInterfaceRealization));
assertTrue(addUMLDependency.getRefinedBy().contains(addSupplierInInterfaceRealization));
assertTrue(addUMLDependency.getRefinedBy().contains(addContractInInterfaceRealization));
- // duplicate diff: NamedElement.clientDependency to InterfaceRealization0
+ assertTrue(addUMLDependency.getRefinedBy().contains(addClientDependencyInClass0));
// CHECK REQUIREMENT
if (kind.equals(TestKind.ADD)) {
@@ -167,11 +174,11 @@ public class AddInterfaceRealizationTest extends AbstractTest {
assertSame(Integer.valueOf(0), Integer.valueOf(addContractInInterfaceRealization.getRequires()
.size()));
- assertSame(Integer.valueOf(3), Integer.valueOf(addInterfaceRealization.getRequires().size()));
+ assertSame(Integer.valueOf(4), Integer.valueOf(addInterfaceRealization.getRequires().size()));
assertTrue(addInterfaceRealization.getRequires().contains(addClientInInterfaceRealization));
assertTrue(addInterfaceRealization.getRequires().contains(addSupplierInInterfaceRealization));
assertTrue(addInterfaceRealization.getRequires().contains(addContractInInterfaceRealization));
- // duplicate diff: NamedElement.clientDependency to InterfaceRealization0
+ assertTrue(addInterfaceRealization.getRequires().contains(addClientDependencyInClass0));
assertSame(Integer.valueOf(0), Integer.valueOf(addUMLDependency.getRequires().size()));
}
@@ -183,8 +190,9 @@ public class AddInterfaceRealizationTest extends AbstractTest {
assertSame(Integer.valueOf(2), Integer.valueOf(addClientInInterfaceRealization.getEquivalence()
.getDifferences().size()));
assertTrue(addClientInInterfaceRealization.getEquivalence().getDifferences().contains(
- addInterfaceRealization));
- // duplicate diff: NamedElement.clientDependency to InterfaceRealization0
+ addClientInInterfaceRealization));
+ assertTrue(addClientInInterfaceRealization.getEquivalence().getDifferences().contains(
+ addClientDependencyInClass0));
testIntersections(comparison);
}
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/dependency/AddSubstitutionTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/dependency/AddSubstitutionTest.java
index 72ef88bdf..ef78100d5 100644
--- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/dependency/AddSubstitutionTest.java
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/dependency/AddSubstitutionTest.java
@@ -85,15 +85,15 @@ public class AddSubstitutionTest extends AbstractTest {
final List<Diff> differences = comparison.getDifferences();
// We should have no less and no more than 6 differences
- assertSame(Integer.valueOf(5), Integer.valueOf(differences.size()));
+ assertSame(Integer.valueOf(6), Integer.valueOf(differences.size()));
Predicate<? super Diff> addInterfaceRealizationDescription = null;
Predicate<? super Diff> addClientInInterfaceRealizationDescription = null;
Predicate<? super Diff> addSupplierInInterfaceRealizationDescription = null;
Predicate<? super Diff> addContractInInterfaceRealizationDescription = null;
+ Predicate<? super Diff> addClientDependencyInClass0Description = null;
if (kind.equals(TestKind.DELETE)) {
- //addInterfaceRealizationDescription = removed("model.Class0.Substitution0"); //$NON-NLS-1$
addInterfaceRealizationDescription = removedFromReference("model.Class0", "substitution",
"model.Class0.Substitution0");
addClientInInterfaceRealizationDescription = removedFromReference("model.Class0.Substitution0",
@@ -102,8 +102,9 @@ public class AddSubstitutionTest extends AbstractTest {
"supplier", "model.Class1");
addContractInInterfaceRealizationDescription = changedReference("model.Class0.Substitution0",
"contract", "model.Class1", null);
+ addClientDependencyInClass0Description = removedFromReference("model.Class0", "clientDependency",
+ "model.Class0.Substitution0");
} else {
- //addInterfaceRealizationDescription = added("model.Class0.Substitution0"); //$NON-NLS-1$
addInterfaceRealizationDescription = addedToReference(
"model.Class0", "substitution", "model.Class0.Substitution0"); //$NON-NLS-1$
addClientInInterfaceRealizationDescription = addedToReference("model.Class0.Substitution0",
@@ -112,6 +113,8 @@ public class AddSubstitutionTest extends AbstractTest {
"supplier", "model.Class1");
addContractInInterfaceRealizationDescription = changedReference("model.Class0.Substitution0",
"contract", null, "model.Class1");
+ addClientDependencyInClass0Description = addedToReference("model.Class0", "clientDependency",
+ "model.Class0.Substitution0");
}
final Diff addInterfaceRealization = Iterators.find(differences.iterator(),
@@ -122,12 +125,14 @@ public class AddSubstitutionTest extends AbstractTest {
addSupplierInInterfaceRealizationDescription);
final Diff addContractInInterfaceRealization = Iterators.find(differences.iterator(),
addContractInInterfaceRealizationDescription);
- // duplicate diff NamedElement.clientDependency to Substitution0
+ final Diff addClientDependencyInClass0 = Iterators.find(differences.iterator(),
+ addClientDependencyInClass0Description);
assertNotNull(addInterfaceRealization);
assertNotNull(addClientInInterfaceRealization);
assertNotNull(addSupplierInInterfaceRealization);
assertNotNull(addContractInInterfaceRealization);
+ assertNotNull(addClientDependencyInClass0);
// CHECK EXTENSION
assertSame(Integer.valueOf(1), count(differences, instanceOf(SubstitutionChange.class)));
@@ -140,12 +145,12 @@ public class AddSubstitutionTest extends AbstractTest {
instanceOf(SubstitutionChange.class), ofKind(DifferenceKind.DELETE)));
}
assertNotNull(addUMLDependency);
- assertSame(Integer.valueOf(4), Integer.valueOf(addUMLDependency.getRefinedBy().size()));
+ assertSame(Integer.valueOf(5), Integer.valueOf(addUMLDependency.getRefinedBy().size()));
assertTrue(addUMLDependency.getRefinedBy().contains(addClientInInterfaceRealization));
assertTrue(addUMLDependency.getRefinedBy().contains(addSupplierInInterfaceRealization));
assertTrue(addUMLDependency.getRefinedBy().contains(addContractInInterfaceRealization));
assertTrue(addUMLDependency.getRefinedBy().contains(addInterfaceRealization));
- // duplicate diff NamedElement.clientDependency to Substitution0
+ assertTrue(addUMLDependency.getRefinedBy().contains(addClientDependencyInClass0));
// CHECK REQUIREMENT
if (kind.equals(TestKind.ADD)) {
@@ -169,11 +174,11 @@ public class AddSubstitutionTest extends AbstractTest {
assertSame(Integer.valueOf(0), Integer.valueOf(addContractInInterfaceRealization.getRequires()
.size()));
- assertSame(Integer.valueOf(3), Integer.valueOf(addInterfaceRealization.getRequires().size()));
+ assertSame(Integer.valueOf(4), Integer.valueOf(addInterfaceRealization.getRequires().size()));
assertTrue(addInterfaceRealization.getRequires().contains(addClientInInterfaceRealization));
assertTrue(addInterfaceRealization.getRequires().contains(addSupplierInInterfaceRealization));
assertTrue(addInterfaceRealization.getRequires().contains(addContractInInterfaceRealization));
- // duplicate diff NamedElement.clientDependency to Substitution0
+ assertTrue(addInterfaceRealization.getRequires().contains(addClientDependencyInClass0));
assertSame(Integer.valueOf(0), Integer.valueOf(addUMLDependency.getRequires().size()));
}
@@ -185,8 +190,9 @@ public class AddSubstitutionTest extends AbstractTest {
assertSame(Integer.valueOf(2), Integer.valueOf(addClientInInterfaceRealization.getEquivalence()
.getDifferences().size()));
assertTrue(addClientInInterfaceRealization.getEquivalence().getDifferences().contains(
- addInterfaceRealization));
- // duplicate diff NamedElement.clientDependency to Substitution0
+ addClientInInterfaceRealization));
+ assertTrue(addClientInInterfaceRealization.getEquivalence().getDifferences().contains(
+ addClientDependencyInClass0));
testIntersections(comparison);
}
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsAssociationTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsAssociationTest.java
new file mode 100644
index 000000000..d92cf52e6
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsAssociationTest.java
@@ -0,0 +1,1036 @@
+package org.eclipse.emf.compare.uml2.tests.implications;
+
+import static com.google.common.base.Predicates.and;
+import static com.google.common.base.Predicates.instanceOf;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.assertTrue;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.added;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.addedToReference;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.changedReference;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.ofKind;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.onEObject;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.onFeature;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.removed;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.removedFromReference;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterators;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.eclipse.emf.common.util.BasicMonitor;
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.DifferenceKind;
+import org.eclipse.emf.compare.tests.framework.AbstractInputData;
+import org.eclipse.emf.compare.uml2.internal.AssociationChange;
+import org.eclipse.emf.compare.uml2.tests.AbstractTest;
+import org.eclipse.emf.compare.uml2.tests.implications.data.ImplicationsInputData;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.junit.Test;
+
+@SuppressWarnings("nls")
+public class ImplicationsAssociationTest extends AbstractTest {
+
+ private static final int NB_DIFFS = 16;
+
+ private ImplicationsInputData input = new ImplicationsInputData();
+
+ private DiffsOfInterest getDiffs(Comparison comparison, TestKind kind) {
+ final List<Diff> differences = comparison.getDifferences();
+ Predicate<? super Diff> addAssociationDescription = null;
+ Predicate<? super Diff> addNavigableOwnedEndClass1InAssociationDescription = null;
+ Predicate<? super Diff> addNavigableOwnedEndClass2InAssociationDescription = null;
+ Predicate<? super Diff> addRefAssociationInPropertyClass1Description = null;
+ Predicate<? super Diff> addRefTypeInPropertyClass1Description = null;
+ Predicate<? super Diff> addRefAssociationInPropertyClass2Description = null;
+ Predicate<? super Diff> addRefTypeInPropertyClass2Description = null;
+ Predicate<? super Diff> addLiteralIntegerInClass1Description = null;
+ Predicate<? super Diff> addUnlimitedNaturalInClass1Description = null;
+ Predicate<? super Diff> addLiteralIntegerInClass2Description = null;
+ Predicate<? super Diff> addUnlimitedNaturalInClass2Description = null;
+ Predicate<? super Diff> addMemberEndClass1InAssociationDescription = null;
+ Predicate<? super Diff> addMemberEndClass2InAssociationDescription = null;
+ Predicate<? super Diff> addOwnedEndClass1Description = null;
+ Predicate<? super Diff> addOwnedEndClass2Description = null;
+
+ if (kind.equals(TestKind.DELETE)) {
+ addAssociationDescription = removed("myModel.class1sToClass2s"); //$NON-NLS-1$
+ addNavigableOwnedEndClass1InAssociationDescription = removedFromReference(
+ "myModel.class1sToClass2s", "navigableOwnedEnd", "myModel.class1sToClass2s.class1s");
+ addNavigableOwnedEndClass2InAssociationDescription = removedFromReference(
+ "myModel.class1sToClass2s", "navigableOwnedEnd", "myModel.class1sToClass2s.class2s");
+ addRefAssociationInPropertyClass1Description = changedReference(
+ "myModel.class1sToClass2s.class1s", "association", "myModel.class1sToClass2s", null);
+ addRefTypeInPropertyClass1Description = changedReference("myModel.class1sToClass2s.class1s",
+ "type", "myModel.Class1", null);
+ addRefAssociationInPropertyClass2Description = changedReference(
+ "myModel.class1sToClass2s.class2s", "association", "myModel.class1sToClass2s", null);
+ addRefTypeInPropertyClass2Description = changedReference("myModel.class1sToClass2s.class2s",
+ "type", "myModel.Class2", null);
+ addLiteralIntegerInClass1Description = removedLowerValueIn("myModel.class1sToClass2s.class1s");
+ addUnlimitedNaturalInClass1Description = removedUpperValueIn("myModel.class1sToClass2s.class1s");
+ addLiteralIntegerInClass2Description = removedLowerValueIn("myModel.class1sToClass2s.class2s");
+ addUnlimitedNaturalInClass2Description = removedUpperValueIn("myModel.class1sToClass2s.class2s");
+ addMemberEndClass1InAssociationDescription = removedFromReference("myModel.class1sToClass2s",
+ "memberEnd", "myModel.class1sToClass2s.class1s");
+ addMemberEndClass2InAssociationDescription = removedFromReference("myModel.class1sToClass2s",
+ "memberEnd", "myModel.class1sToClass2s.class2s");
+ addOwnedEndClass1Description = removedFromReference("myModel.class1sToClass2s", "ownedEnd",
+ "myModel.class1sToClass2s.class1s");
+ addOwnedEndClass2Description = removedFromReference("myModel.class1sToClass2s", "ownedEnd",
+ "myModel.class1sToClass2s.class2s");
+ } else {
+ addAssociationDescription = added("myModel.class1sToClass2s"); //$NON-NLS-1$
+ addNavigableOwnedEndClass1InAssociationDescription = addedToReference("myModel.class1sToClass2s",
+ "navigableOwnedEnd", "myModel.class1sToClass2s.class1s");
+ addNavigableOwnedEndClass2InAssociationDescription = addedToReference("myModel.class1sToClass2s",
+ "navigableOwnedEnd", "myModel.class1sToClass2s.class2s");
+ addRefAssociationInPropertyClass1Description = changedReference(
+ "myModel.class1sToClass2s.class1s", "association", null, "myModel.class1sToClass2s");
+ addRefTypeInPropertyClass1Description = changedReference("myModel.class1sToClass2s.class1s",
+ "type", null, "myModel.Class1");
+ addRefAssociationInPropertyClass2Description = changedReference(
+ "myModel.class1sToClass2s.class2s", "association", null, "myModel.class1sToClass2s");
+ addRefTypeInPropertyClass2Description = changedReference("myModel.class1sToClass2s.class2s",
+ "type", null, "myModel.Class2");
+ addLiteralIntegerInClass1Description = addedLowerValueIn("myModel.class1sToClass2s.class1s");
+ addUnlimitedNaturalInClass1Description = addedUpperValueIn("myModel.class1sToClass2s.class1s");
+ addLiteralIntegerInClass2Description = addedLowerValueIn("myModel.class1sToClass2s.class2s");
+ addUnlimitedNaturalInClass2Description = addedUpperValueIn("myModel.class1sToClass2s.class2s");
+ addMemberEndClass1InAssociationDescription = addedToReference("myModel.class1sToClass2s",
+ "memberEnd", "myModel.class1sToClass2s.class1s");
+ addMemberEndClass2InAssociationDescription = addedToReference("myModel.class1sToClass2s",
+ "memberEnd", "myModel.class1sToClass2s.class2s");
+ addOwnedEndClass1Description = addedToReference("myModel.class1sToClass2s", "ownedEnd",
+ "myModel.class1sToClass2s.class1s");
+ addOwnedEndClass2Description = addedToReference("myModel.class1sToClass2s", "ownedEnd",
+ "myModel.class1sToClass2s.class2s");
+ }
+
+ DiffsOfInterest diffs = new DiffsOfInterest();
+ diffs.addAssociation = Iterators.find(differences.iterator(), addAssociationDescription, null);
+ diffs.addNavigableOwnedEndClass1InAssociation = Iterators.find(differences.iterator(),
+ addNavigableOwnedEndClass1InAssociationDescription, null);
+ diffs.addNavigableOwnedEndClass2InAssociation = Iterators.find(differences.iterator(),
+ addNavigableOwnedEndClass2InAssociationDescription, null);
+ diffs.addMemberEndClass1InAssociation = Iterators.find(differences.iterator(),
+ addMemberEndClass1InAssociationDescription, null);
+ diffs.addMemberEndClass2InAssociation = Iterators.find(differences.iterator(),
+ addMemberEndClass2InAssociationDescription, null);
+ diffs.addOwnedEndClass1InAssociation = Iterators.find(differences.iterator(),
+ addOwnedEndClass1Description, null);
+ diffs.addOwnedEndClass2InAssociation = Iterators.find(differences.iterator(),
+ addOwnedEndClass2Description, null);
+ diffs.addUMLAssociation = Iterators.find(differences.iterator(), instanceOf(AssociationChange.class),
+ null);
+ diffs.addRefAssociationInPropertyClass1 = Iterators.find(differences.iterator(),
+ addRefAssociationInPropertyClass1Description, null);
+ diffs.addRefTypeInPropertyClass1 = Iterators.find(differences.iterator(),
+ addRefTypeInPropertyClass1Description, null);
+ diffs.addRefAssociationInPropertyClass2 = Iterators.find(differences.iterator(),
+ addRefAssociationInPropertyClass2Description, null);
+ diffs.addRefTypeInPropertyClass2 = Iterators.find(differences.iterator(),
+ addRefTypeInPropertyClass2Description, null);
+ diffs.addLiteralIntegerInClass1 = Iterators.find(differences.iterator(),
+ addLiteralIntegerInClass1Description, null);
+ diffs.addUnlimitedNaturalInClass1 = Iterators.find(differences.iterator(),
+ addUnlimitedNaturalInClass1Description, null);
+ diffs.addLiteralIntegerInClass2 = Iterators.find(differences.iterator(),
+ addLiteralIntegerInClass2Description, null);
+ diffs.addUnlimitedNaturalInClass2 = Iterators.find(differences.iterator(),
+ addUnlimitedNaturalInClass2Description, null);
+
+ return diffs;
+ }
+
+ @Test
+ public void testA10UseCase() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right);
+ testAB1(TestKind.ADD, comparison);
+ }
+
+ @Test
+ // local ADD
+ public void testA10UseCase3way1() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right, right);
+ testAB1(TestKind.ADD, comparison);
+ }
+
+ @Test
+ // remote ADD
+ public void testA10UseCase3way2() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right, left);
+ testAB1(TestKind.ADD, comparison);
+ }
+
+ @Test
+ public void testA10MergeLtR1UseCase() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation)
+ .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddNavigableOwnedEnd(comparison, diffs);
+ }
+
+ private void checkMergeAddNavigableOwnedEnd(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 6, comparison.getDifferences().size());
+ assertNull(diffs.addNavigableOwnedEndClass1InAssociation);
+ assertNull(diffs.addOwnedEndClass1InAssociation);
+ assertNull(diffs.addMemberEndClass1InAssociation);
+ assertNull(diffs.addRefAssociationInPropertyClass1);
+ assertNull(diffs.addAssociation);
+ assertNull(diffs.addUMLAssociation);
+ }
+
+ @Test
+ public void testA10MergeLtR1UseCase3way1() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation)
+ .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddNavigableOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeLtR1UseCase3way2() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation)
+ .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteNavigableOwnedEnd(comparison, diffs);
+ }
+
+ private void checkMergeDeleteNavigableOwnedEnd(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 1, comparison.getDifferences().size());
+ assertNull(diffs.addNavigableOwnedEndClass1InAssociation);
+ }
+
+ @Test
+ public void testA10MergeLtR2UseCase() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation).copyLeftToRight(
+ diffs.addOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddOwnedEnd(comparison, diffs);
+ }
+
+ private void checkMergeAddOwnedEnd(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 5, comparison.getDifferences().size());
+ assertNull(diffs.addOwnedEndClass1InAssociation);
+ assertNull(diffs.addMemberEndClass1InAssociation);
+ assertNull(diffs.addRefAssociationInPropertyClass1);
+ assertNull(diffs.addAssociation);
+ assertNull(diffs.addUMLAssociation);
+ }
+
+ @Test
+ public void testA10MergeLtR2UseCase3way1() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation).copyLeftToRight(
+ diffs.addOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeLtR2UseCase3way2() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation).copyLeftToRight(
+ diffs.addOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteOwnedEnd(comparison, diffs);
+ }
+
+ private void checkMergeDeleteOwnedEnd(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 7, comparison.getDifferences().size());
+ assertNull(diffs.addOwnedEndClass1InAssociation);
+ assertNull(diffs.addMemberEndClass1InAssociation);
+ assertNull(diffs.addRefAssociationInPropertyClass1);
+ assertNull(diffs.addNavigableOwnedEndClass1InAssociation);
+ assertNull(diffs.addLiteralIntegerInClass1);
+ assertNull(diffs.addUnlimitedNaturalInClass1);
+ assertNull(diffs.addRefTypeInPropertyClass1);
+ }
+
+ @Test
+ public void testA10MergeLtR3UseCase() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation).copyLeftToRight(
+ diffs.addMemberEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddMemberEnd(comparison, diffs);
+ }
+
+ private void checkMergeAddMemberEnd(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 5, comparison.getDifferences().size());
+ assertNull(diffs.addMemberEndClass1InAssociation);
+ assertNull(diffs.addRefAssociationInPropertyClass1);
+ assertNull(diffs.addOwnedEndClass1InAssociation);
+ assertNull(diffs.addAssociation);
+ assertNull(diffs.addUMLAssociation);
+ }
+
+ @Test
+ public void testA10MergeLtR3UseCase3way1() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation).copyLeftToRight(
+ diffs.addMemberEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddMemberEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeLtR3UseCase3way2() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation).copyLeftToRight(
+ diffs.addMemberEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL1UseCase() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation)
+ .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteNavigableOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL1UseCase3way1() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation)
+ .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteNavigableOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL1UseCase3way2() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation)
+ .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddNavigableOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL2UseCase() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation).copyRightToLeft(
+ diffs.addOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL2UseCase3way1() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation).copyRightToLeft(
+ diffs.addOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL2UseCase3way2() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation).copyRightToLeft(
+ diffs.addOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL3UseCase() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation).copyRightToLeft(
+ diffs.addMemberEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL3UseCase3way1() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation).copyRightToLeft(
+ diffs.addMemberEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL3UseCase3way2() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation).copyRightToLeft(
+ diffs.addMemberEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddMemberEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11UseCase() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right);
+ testAB1(TestKind.DELETE, comparison);
+ }
+
+ @Test
+ // local DELETE
+ public void testA11UseCase3way1() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right, right);
+ testAB1(TestKind.DELETE, comparison);
+ }
+
+ @Test
+ // remote DELETE
+ public void testA11UseCase3way2() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right, left);
+ testAB1(TestKind.DELETE, comparison);
+ }
+
+ @Test
+ public void testA11MergeLtR1UseCase() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation)
+ .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteNavigableOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR1UseCase3way1() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation)
+ .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteNavigableOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR1UseCase3way2() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation)
+ .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddNavigableOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR2UseCase() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation).copyLeftToRight(
+ diffs.addOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR2UseCase3way1() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation).copyLeftToRight(
+ diffs.addOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR2UseCase3way2() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation).copyLeftToRight(
+ diffs.addOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR3UseCase() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation).copyLeftToRight(
+ diffs.addMemberEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR3UseCase3way1() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation).copyLeftToRight(
+ diffs.addMemberEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR3UseCase3way2() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation).copyLeftToRight(
+ diffs.addMemberEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddMemberEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL1UseCase() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation)
+ .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddNavigableOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL1UseCase3way1() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation)
+ .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddNavigableOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL1UseCase3way2() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation)
+ .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteNavigableOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL2UseCase() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation).copyRightToLeft(
+ diffs.addOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL2UseCase3way1() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation).copyRightToLeft(
+ diffs.addOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL2UseCase3way2() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation).copyRightToLeft(
+ diffs.addOwnedEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteOwnedEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL3UseCase() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation).copyRightToLeft(
+ diffs.addMemberEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddMemberEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL3UseCase3way1() throws IOException {
+ final Resource left = input.getA1Right();
+ final Resource right = input.getA1Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation).copyRightToLeft(
+ diffs.addMemberEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddMemberEnd(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL3UseCase3way2() throws IOException {
+ final Resource left = input.getA1Left();
+ final Resource right = input.getA1Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation).copyRightToLeft(
+ diffs.addMemberEndClass1InAssociation, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteOwnedEnd(comparison, diffs);
+ }
+
+ private void testAB1(TestKind kind, final Comparison comparison) {
+ final List<Diff> differences = comparison.getDifferences();
+
+ // We should have no less and no more than 16 differences
+ assertSame(Integer.valueOf(NB_DIFFS), Integer.valueOf(differences.size()));
+
+ DiffsOfInterest diffs = getDiffs(comparison, kind);
+
+ if (kind.equals(TestKind.DELETE)) {
+ assertEquals(0, diffs.addNavigableOwnedEndClass1InAssociation.getImplies().size());
+ assertEquals(1, diffs.addNavigableOwnedEndClass1InAssociation.getImpliedBy().size());
+ assertTrue(diffs.addNavigableOwnedEndClass1InAssociation.getImpliedBy().contains(
+ diffs.addOwnedEndClass1InAssociation));
+
+ assertEquals(1, diffs.addOwnedEndClass1InAssociation.getImplies().size());
+ assertTrue(diffs.addOwnedEndClass1InAssociation.getImplies().contains(
+ diffs.addNavigableOwnedEndClass1InAssociation));
+ assertEquals(1, diffs.addOwnedEndClass1InAssociation.getImpliedBy().size());
+ assertTrue(diffs.addOwnedEndClass1InAssociation.getImpliedBy().contains(
+ diffs.addMemberEndClass1InAssociation));
+
+ assertEquals(1, diffs.addMemberEndClass1InAssociation.getImplies().size());
+ assertTrue(diffs.addMemberEndClass1InAssociation.getImplies().contains(
+ diffs.addOwnedEndClass1InAssociation));
+ assertEquals(0, diffs.addMemberEndClass1InAssociation.getImpliedBy().size());
+ } else {
+ assertEquals(1, diffs.addNavigableOwnedEndClass1InAssociation.getImplies().size());
+ assertTrue(diffs.addNavigableOwnedEndClass1InAssociation.getImplies().contains(
+ diffs.addOwnedEndClass1InAssociation));
+ assertEquals(0, diffs.addNavigableOwnedEndClass1InAssociation.getImpliedBy().size());
+
+ assertEquals(1, diffs.addOwnedEndClass1InAssociation.getImplies().size());
+ assertTrue(diffs.addOwnedEndClass1InAssociation.getImplies().contains(
+ diffs.addMemberEndClass1InAssociation));
+ assertEquals(1, diffs.addOwnedEndClass1InAssociation.getImpliedBy().size());
+ assertTrue(diffs.addOwnedEndClass1InAssociation.getImpliedBy().contains(
+ diffs.addNavigableOwnedEndClass1InAssociation));
+
+ assertEquals(0, diffs.addMemberEndClass1InAssociation.getImplies().size());
+ assertEquals(1, diffs.addMemberEndClass1InAssociation.getImpliedBy().size());
+ assertTrue(diffs.addMemberEndClass1InAssociation.getImpliedBy().contains(
+ diffs.addOwnedEndClass1InAssociation));
+ }
+
+ }
+
+ @Override
+ protected AbstractInputData getInput() {
+ return input;
+ }
+
+ private static Predicate<? super Diff> addedLowerValueIn(final String qualifiedName) {
+ return and(ofKind(DifferenceKind.ADD), onEObject(qualifiedName), onFeature("lowerValue"));
+ }
+
+ private static Predicate<? super Diff> addedUpperValueIn(final String qualifiedName) {
+ return and(ofKind(DifferenceKind.ADD), onEObject(qualifiedName), onFeature("upperValue"));
+ }
+
+ private static Predicate<? super Diff> removedLowerValueIn(final String qualifiedName) {
+ return and(ofKind(DifferenceKind.DELETE), onEObject(qualifiedName), onFeature("lowerValue"));
+ }
+
+ private static Predicate<? super Diff> removedUpperValueIn(final String qualifiedName) {
+ return and(ofKind(DifferenceKind.DELETE), onEObject(qualifiedName), onFeature("upperValue"));
+ }
+
+ private class DiffsOfInterest {
+ public Diff addAssociation;
+
+ public Diff addNavigableOwnedEndClass1InAssociation;
+
+ public Diff addNavigableOwnedEndClass2InAssociation;
+
+ public Diff addMemberEndClass1InAssociation;
+
+ public Diff addMemberEndClass2InAssociation;
+
+ public Diff addOwnedEndClass1InAssociation;
+
+ public Diff addOwnedEndClass2InAssociation;
+
+ public Diff addRefAssociationInPropertyClass1;
+
+ public Diff addRefTypeInPropertyClass1;
+
+ public Diff addRefAssociationInPropertyClass2;
+
+ public Diff addRefTypeInPropertyClass2;
+
+ public Diff addLiteralIntegerInClass1;
+
+ public Diff addUnlimitedNaturalInClass1;
+
+ public Diff addLiteralIntegerInClass2;
+
+ public Diff addUnlimitedNaturalInClass2;
+
+ public Diff addUMLAssociation;
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsInterfaceRealizationTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsInterfaceRealizationTest.java
new file mode 100644
index 000000000..ae93da81f
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsInterfaceRealizationTest.java
@@ -0,0 +1,962 @@
+package org.eclipse.emf.compare.uml2.tests.implications;
+
+import static com.google.common.base.Predicates.instanceOf;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.assertTrue;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.addedToReference;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.changedReference;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.removedFromReference;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterators;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.eclipse.emf.common.util.BasicMonitor;
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.tests.framework.AbstractInputData;
+import org.eclipse.emf.compare.uml2.internal.InterfaceRealizationChange;
+import org.eclipse.emf.compare.uml2.internal.SubstitutionChange;
+import org.eclipse.emf.compare.uml2.tests.AbstractTest;
+import org.eclipse.emf.compare.uml2.tests.implications.data.ImplicationsInputData;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.junit.Test;
+
+@SuppressWarnings("nls")
+public class ImplicationsInterfaceRealizationTest extends AbstractTest {
+
+ private static final int NB_DIFFS = 11;
+
+ private ImplicationsInputData input = new ImplicationsInputData();
+
+ private DiffsOfInterest getDiffs(Comparison comparison, TestKind kind) {
+ final List<Diff> differences = comparison.getDifferences();
+
+ Predicate<? super Diff> addInterfaceRealizationDescription = null;
+ Predicate<? super Diff> addClientInInterfaceRealizationDescription = null;
+ Predicate<? super Diff> addSupplierInInterfaceRealizationDescription = null;
+ Predicate<? super Diff> addContractInInterfaceRealizationDescription = null;
+ Predicate<? super Diff> addClientDependencyInClass0Description = null;
+ Predicate<? super Diff> addSubstitutionDescription = null;
+ Predicate<? super Diff> addClientInSubstitutionDescription = null;
+ Predicate<? super Diff> addSupplierInSubstitutionDescription = null;
+ Predicate<? super Diff> addClientDependencyInClass0Description2 = null;
+ Predicate<? super Diff> addUMLInterfaceRealizationDescription = null;
+ Predicate<? super Diff> addUMLSubstitutionDescription = null;
+
+ if (kind.equals(TestKind.DELETE)) {
+ addInterfaceRealizationDescription = removedFromReference("model.Class0", "interfaceRealization",
+ "model.Class0.InterfaceRealization0");
+ addClientInInterfaceRealizationDescription = removedFromReference(
+ "model.Class0.InterfaceRealization0", "client", "model.Class0");
+ addSupplierInInterfaceRealizationDescription = removedFromReference(
+ "model.Class0.InterfaceRealization0", "supplier", "model.Interface0");
+ addContractInInterfaceRealizationDescription = changedReference(
+ "model.Class0.InterfaceRealization0", "contract", "model.Interface0", null);
+ addClientDependencyInClass0Description = removedFromReference("model.Class0", "clientDependency",
+ "model.Class0.InterfaceRealization0");
+ addSubstitutionDescription = removedFromReference("model.Class0", "substitution",
+ "model.Class0.substitution1");
+ addClientInSubstitutionDescription = removedFromReference("model.Class0.substitution1", "client",
+ "model.Class0");
+ addSupplierInSubstitutionDescription = removedFromReference("model.Class0.substitution1",
+ "supplier", "model.Interface0");
+ addClientDependencyInClass0Description2 = removedFromReference("model.Class0",
+ "clientDependency", "model.Class0.substitution1");
+ } else {
+ addInterfaceRealizationDescription = addedToReference(
+ "model.Class0", "interfaceRealization", "model.Class0.InterfaceRealization0"); //$NON-NLS-1$
+ addClientInInterfaceRealizationDescription = addedToReference(
+ "model.Class0.InterfaceRealization0", "client", "model.Class0");
+ addSupplierInInterfaceRealizationDescription = addedToReference(
+ "model.Class0.InterfaceRealization0", "supplier", "model.Interface0");
+ addContractInInterfaceRealizationDescription = changedReference(
+ "model.Class0.InterfaceRealization0", "contract", null, "model.Interface0");
+ addClientDependencyInClass0Description = addedToReference("model.Class0", "clientDependency",
+ "model.Class0.InterfaceRealization0");
+ addSubstitutionDescription = addedToReference("model.Class0", "substitution",
+ "model.Class0.substitution1");
+ addClientInSubstitutionDescription = addedToReference("model.Class0.substitution1", "client",
+ "model.Class0");
+ addSupplierInSubstitutionDescription = addedToReference("model.Class0.substitution1", "supplier",
+ "model.Interface0");
+ addClientDependencyInClass0Description2 = addedToReference("model.Class0", "clientDependency",
+ "model.Class0.substitution1");
+ }
+
+ DiffsOfInterest diffs = new DiffsOfInterest();
+ diffs.addInterfaceRealization = Iterators.find(differences.iterator(),
+ addInterfaceRealizationDescription, null);
+ diffs.addClientInInterfaceRealization = Iterators.find(differences.iterator(),
+ addClientInInterfaceRealizationDescription, null);
+ diffs.addSupplierInInterfaceRealization = Iterators.find(differences.iterator(),
+ addSupplierInInterfaceRealizationDescription, null);
+ diffs.addContractInInterfaceRealization = Iterators.find(differences.iterator(),
+ addContractInInterfaceRealizationDescription, null);
+ diffs.addClientDependencyInClass0 = Iterators.find(differences.iterator(),
+ addClientDependencyInClass0Description, null);
+ diffs.addSubstitution = Iterators.find(differences.iterator(), addSubstitutionDescription, null);
+ diffs.addClientInSubstitution = Iterators.find(differences.iterator(),
+ addClientInSubstitutionDescription, null);
+ diffs.addSupplierInSubstitution = Iterators.find(differences.iterator(),
+ addSupplierInSubstitutionDescription, null);
+ diffs.addClientDependencyInClass02 = Iterators.find(differences.iterator(),
+ addClientDependencyInClass0Description2, null);
+ diffs.addUMLInterfaceRealization = Iterators.find(differences.iterator(),
+ instanceOf(InterfaceRealizationChange.class), null);
+ diffs.addUMLSubstitution = Iterators.find(differences.iterator(),
+ instanceOf(SubstitutionChange.class), null);
+ return diffs;
+ }
+
+ @Test
+ public void testA10UseCase() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right);
+ testAB1(TestKind.ADD, comparison);
+ }
+
+ @Test
+ // local ADD
+ public void testA10UseCase3way1() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right, right);
+ testAB1(TestKind.ADD, comparison);
+ }
+
+ @Test
+ // remote ADD
+ public void testA10UseCase3way2() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right, left);
+ testAB1(TestKind.ADD, comparison);
+ }
+
+ @Test
+ public void testA10MergeLtR1UseCase() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization).copyLeftToRight(
+ diffs.addClientInInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddClientInInterfaceRealization(comparison, diffs);
+ }
+
+ private void checkMergeAddClientInInterfaceRealization(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 3, comparison.getDifferences().size());
+ assertNull(diffs.addClientInInterfaceRealization);
+ assertNull(diffs.addInterfaceRealization);
+ assertNull(diffs.addClientDependencyInClass0);
+ }
+
+ @Test
+ public void testA10MergeLtR1UseCase3way1() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization).copyLeftToRight(
+ diffs.addClientInInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddClientInInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeLtR1UseCase3way2() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization).copyLeftToRight(
+ diffs.addClientInInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteClientInInterfaceRealization(comparison, diffs);
+ }
+
+ private void checkMergeDeleteClientInInterfaceRealization(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 6, comparison.getDifferences().size());
+ assertNull(diffs.addClientInInterfaceRealization);
+ assertNull(diffs.addClientDependencyInClass0);
+ assertNull(diffs.addInterfaceRealization);
+ assertNull(diffs.addSupplierInInterfaceRealization);
+ assertNull(diffs.addContractInInterfaceRealization);
+ assertNull(diffs.addUMLInterfaceRealization);
+ }
+
+ @Test
+ public void testA10MergeLtR2UseCase() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientDependencyInClass0).copyLeftToRight(
+ diffs.addClientDependencyInClass0, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddClientDependencyInClass0(comparison, diffs);
+ }
+
+ private void checkMergeAddClientDependencyInClass0(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 3, comparison.getDifferences().size());
+ assertNull(diffs.addClientDependencyInClass0);
+ assertNull(diffs.addClientInInterfaceRealization);
+ assertNull(diffs.addInterfaceRealization);
+ }
+
+ @Test
+ public void testA10MergeLtR2UseCase3way1() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientDependencyInClass0).copyLeftToRight(
+ diffs.addClientDependencyInClass0, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddClientDependencyInClass0(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeLtR2UseCase3way2() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientDependencyInClass0).copyLeftToRight(
+ diffs.addClientDependencyInClass0, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteClientDependencyInClass0(comparison, diffs);
+ }
+
+ private void checkMergeDeleteClientDependencyInClass0(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 6, comparison.getDifferences().size());
+ assertNull(diffs.addClientDependencyInClass0);
+ assertNull(diffs.addClientInInterfaceRealization);
+ assertNull(diffs.addInterfaceRealization);
+ assertNull(diffs.addSupplierInInterfaceRealization);
+ assertNull(diffs.addContractInInterfaceRealization);
+ assertNull(diffs.addUMLInterfaceRealization);
+ }
+
+ @Test
+ public void testA10MergeLtR3UseCase() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization).copyLeftToRight(
+ diffs.addInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddInterfaceRealization(comparison, diffs);
+ }
+
+ private void checkMergeAddInterfaceRealization(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 3, comparison.getDifferences().size());
+ assertNull(diffs.addInterfaceRealization);
+ assertNull(diffs.addClientDependencyInClass0);
+ assertNull(diffs.addClientInInterfaceRealization);
+ }
+
+ @Test
+ public void testA10MergeLtR3UseCase3way1() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization).copyLeftToRight(
+ diffs.addInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeLtR3UseCase3way2() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization).copyLeftToRight(
+ diffs.addInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteInterfaceRealization(comparison, diffs);
+ }
+
+ private void checkMergeDeleteInterfaceRealization(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 6, comparison.getDifferences().size());
+ assertNull(diffs.addInterfaceRealization);
+ assertNull(diffs.addClientInInterfaceRealization);
+ assertNull(diffs.addSupplierInInterfaceRealization);
+ assertNull(diffs.addContractInInterfaceRealization);
+ assertNull(diffs.addClientDependencyInClass0);
+ assertNull(diffs.addUMLInterfaceRealization);
+ }
+
+ @Test
+ public void testA10MergeRtL1UseCase() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization).copyRightToLeft(
+ diffs.addClientInInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteClientInInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL1UseCase3way1() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization).copyRightToLeft(
+ diffs.addClientInInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteClientInInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL1UseCase3way2() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization).copyRightToLeft(
+ diffs.addClientInInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddClientInInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL2UseCase() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientDependencyInClass0).copyRightToLeft(
+ diffs.addClientDependencyInClass0, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteClientDependencyInClass0(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL2UseCase3way1() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientDependencyInClass0).copyRightToLeft(
+ diffs.addClientDependencyInClass0, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteClientDependencyInClass0(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL2UseCase3way2() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientDependencyInClass0).copyRightToLeft(
+ diffs.addClientDependencyInClass0, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddClientDependencyInClass0(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL3UseCase() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization).copyRightToLeft(
+ diffs.addInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL3UseCase3way1() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization).copyRightToLeft(
+ diffs.addInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL3UseCase3way2() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization).copyRightToLeft(
+ diffs.addInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA11UseCase() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right);
+ testAB1(TestKind.DELETE, comparison);
+ }
+
+ @Test
+ // local DELETE
+ public void testA11UseCase3way1() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right, right);
+ testAB1(TestKind.DELETE, comparison);
+ }
+
+ @Test
+ // remote DELETE
+ public void testA11UseCase3way2() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right, left);
+ testAB1(TestKind.DELETE, comparison);
+ }
+
+ @Test
+ public void testA11MergeLtR1UseCase() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization).copyLeftToRight(
+ diffs.addClientInInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteClientInInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR1UseCase3way1() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization).copyLeftToRight(
+ diffs.addClientInInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteClientInInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR1UseCase3way2() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization).copyLeftToRight(
+ diffs.addClientInInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddClientInInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR2UseCase() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientDependencyInClass0).copyLeftToRight(
+ diffs.addClientDependencyInClass0, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteClientDependencyInClass0(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR2UseCase3way1() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientDependencyInClass0).copyLeftToRight(
+ diffs.addClientDependencyInClass0, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteClientDependencyInClass0(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR2UseCase3way2() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientDependencyInClass0).copyLeftToRight(
+ diffs.addClientDependencyInClass0, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddClientDependencyInClass0(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR3UseCase() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization).copyLeftToRight(
+ diffs.addInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR3UseCase3way1() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization).copyLeftToRight(
+ diffs.addInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR3UseCase3way2() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization).copyLeftToRight(
+ diffs.addInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL1UseCase() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization).copyRightToLeft(
+ diffs.addClientInInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddClientInInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL1UseCase3way1() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization).copyRightToLeft(
+ diffs.addClientInInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddClientInInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL1UseCase3way2() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization).copyRightToLeft(
+ diffs.addClientInInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteClientInInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL2UseCase() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientDependencyInClass0).copyRightToLeft(
+ diffs.addClientDependencyInClass0, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddClientDependencyInClass0(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL2UseCase3way1() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientDependencyInClass0).copyRightToLeft(
+ diffs.addClientDependencyInClass0, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddClientDependencyInClass0(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL2UseCase3way2() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addClientDependencyInClass0).copyRightToLeft(
+ diffs.addClientDependencyInClass0, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteClientDependencyInClass0(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL3UseCase() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization).copyRightToLeft(
+ diffs.addInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL3UseCase3way1() throws IOException {
+ final Resource left = input.getA3Right();
+ final Resource right = input.getA3Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization).copyRightToLeft(
+ diffs.addInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddInterfaceRealization(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL3UseCase3way2() throws IOException {
+ final Resource left = input.getA3Left();
+ final Resource right = input.getA3Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization).copyRightToLeft(
+ diffs.addInterfaceRealization, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteInterfaceRealization(comparison, diffs);
+ }
+
+ private void testAB1(TestKind kind, final Comparison comparison) {
+ final List<Diff> differences = comparison.getDifferences();
+
+ assertSame(Integer.valueOf(NB_DIFFS), Integer.valueOf(differences.size()));
+
+ DiffsOfInterest diffs = getDiffs(comparison, kind);
+
+ if (kind.equals(TestKind.DELETE)) {
+ assertEquals(1, diffs.addClientDependencyInClass0.getImplies().size());
+ assertTrue(diffs.addClientDependencyInClass0.getImplies().contains(diffs.addInterfaceRealization));
+
+ assertEquals(1, diffs.addClientDependencyInClass02.getImplies().size());
+ assertTrue(diffs.addClientDependencyInClass02.getImplies().contains(diffs.addSubstitution));
+ } else {
+ assertEquals(1, diffs.addInterfaceRealization.getImplies().size());
+ assertTrue(diffs.addInterfaceRealization.getImplies().contains(diffs.addClientDependencyInClass0));
+
+ assertEquals(1, diffs.addSubstitution.getImplies().size());
+ assertTrue(diffs.addSubstitution.getImplies().contains(diffs.addClientDependencyInClass02));
+ }
+ assertEquals(0, diffs.addClientInInterfaceRealization.getImplies().size());
+ assertEquals(0, diffs.addClientInSubstitution.getImplies().size());
+
+ }
+
+ @Override
+ protected AbstractInputData getInput() {
+ return input;
+ }
+
+ private class DiffsOfInterest {
+ public Diff addInterfaceRealization;
+
+ public Diff addClientInInterfaceRealization;
+
+ public Diff addSupplierInInterfaceRealization;
+
+ public Diff addContractInInterfaceRealization;
+
+ public Diff addClientDependencyInClass0;
+
+ public Diff addSubstitution;
+
+ public Diff addClientInSubstitution;
+
+ public Diff addSupplierInSubstitution;
+
+ public Diff addClientDependencyInClass02;
+
+ public Diff addUMLInterfaceRealization;
+
+ public Diff addUMLSubstitution;
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsTransitionTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsTransitionTest.java
new file mode 100644
index 000000000..df677a5bd
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsTransitionTest.java
@@ -0,0 +1,901 @@
+package org.eclipse.emf.compare.uml2.tests.implications;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.assertTrue;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.added;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.addedToReference;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.changedReference;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.removed;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.removedFromReference;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterators;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.eclipse.emf.common.util.BasicMonitor;
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.tests.framework.AbstractInputData;
+import org.eclipse.emf.compare.uml2.tests.AbstractTest;
+import org.eclipse.emf.compare.uml2.tests.implications.data.ImplicationsInputData;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.junit.Test;
+
+@SuppressWarnings("nls")
+public class ImplicationsTransitionTest extends AbstractTest {
+
+ private static final int NB_DIFFS = 6;
+
+ private ImplicationsInputData input = new ImplicationsInputData();
+
+ private DiffsOfInterest getDiffs(Comparison comparison, TestKind kind) {
+ final List<Diff> differences = comparison.getDifferences();
+ Predicate<? super Diff> addTransitionDescription = null;
+ Predicate<? super Diff> addPreConditionDescription = null;
+ Predicate<? super Diff> addOwnedRuleDescription = null;
+ Predicate<? super Diff> addGuardDescription = null;
+
+ if (kind.equals(TestKind.DELETE)) {
+ addTransitionDescription = removed("model.StateMachine0.Region0.transition1"); //$NON-NLS-1$
+ addPreConditionDescription = changedReference("model.StateMachine0.Region0.transition1",
+ "preCondition", "model.StateMachine0.Region0.transition1.rule1", null);
+ addOwnedRuleDescription = removedFromReference("model.StateMachine0.Region0.transition1",
+ "ownedRule", "model.StateMachine0.Region0.transition1.rule1");
+ addGuardDescription = changedReference("model.StateMachine0.Region0.transition1", "guard",
+ "model.StateMachine0.Region0.transition1.rule1", null);
+ } else {
+ addTransitionDescription = added("model.StateMachine0.Region0.transition1"); //$NON-NLS-1$
+ addPreConditionDescription = changedReference("model.StateMachine0.Region0.transition1",
+ "preCondition", null, "model.StateMachine0.Region0.transition1.rule1");
+ addOwnedRuleDescription = addedToReference("model.StateMachine0.Region0.transition1",
+ "ownedRule", "model.StateMachine0.Region0.transition1.rule1");
+ addGuardDescription = changedReference("model.StateMachine0.Region0.transition1", "guard", null,
+ "model.StateMachine0.Region0.transition1.rule1");
+ }
+
+ DiffsOfInterest diffs = new DiffsOfInterest();
+ diffs.addTransition = Iterators.find(differences.iterator(), addTransitionDescription, null);
+ diffs.addPrecondition = Iterators.find(differences.iterator(), addPreConditionDescription, null);
+ diffs.addOwnedRule = Iterators.find(differences.iterator(), addOwnedRuleDescription, null);
+ diffs.addGuard = Iterators.find(differences.iterator(), addGuardDescription, null);
+
+ return diffs;
+ }
+
+ @Test
+ public void testA10UseCase() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right);
+ testAB1(TestKind.ADD, comparison);
+ }
+
+ @Test
+ // local ADD
+ public void testA10UseCase3way1() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right, right);
+ testAB1(TestKind.ADD, comparison);
+ }
+
+ @Test
+ // remote ADD
+ public void testA10UseCase3way2() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right, left);
+ testAB1(TestKind.ADD, comparison);
+ }
+
+ @Test
+ public void testA10MergeLtR1UseCase() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition).copyLeftToRight(
+ diffs.addPrecondition, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddPrecondition(comparison, diffs);
+ }
+
+ private void checkMergeAddPrecondition(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 4, comparison.getDifferences().size());
+ assertNull(diffs.addPrecondition);
+ assertNull(diffs.addGuard);
+ assertNull(diffs.addOwnedRule);
+ assertNull(diffs.addTransition);
+ }
+
+ @Test
+ public void testA10MergeLtR1UseCase3way1() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition).copyLeftToRight(
+ diffs.addPrecondition, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddPrecondition(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeLtR1UseCase3way2() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition).copyLeftToRight(
+ diffs.addPrecondition, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeletePrecondition(comparison, diffs);
+ }
+
+ private void checkMergeDeletePrecondition(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 1, comparison.getDifferences().size());
+ assertNull(diffs.addPrecondition);
+ }
+
+ @Test
+ public void testA10MergeLtR2UseCase() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyLeftToRight(diffs.addGuard,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddGuard(comparison, diffs);
+ }
+
+ private void checkMergeAddGuard(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 3, comparison.getDifferences().size());
+ assertNull(diffs.addGuard);
+ assertNull(diffs.addOwnedRule);
+ assertNull(diffs.addTransition);
+ }
+
+ @Test
+ public void testA10MergeLtR2UseCase3way1() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyLeftToRight(diffs.addGuard,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddGuard(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeLtR2UseCase3way2() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyLeftToRight(diffs.addGuard,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteGuard(comparison, diffs);
+ }
+
+ private void checkMergeDeleteGuard(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 2, comparison.getDifferences().size());
+ assertNull(diffs.addGuard);
+ assertNull(diffs.addPrecondition);
+ }
+
+ @Test
+ public void testA10MergeLtR3UseCase() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyLeftToRight(diffs.addOwnedRule,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddOwnedRule(comparison, diffs);
+ }
+
+ private void checkMergeAddOwnedRule(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 2, comparison.getDifferences().size());
+ assertNull(diffs.addOwnedRule);
+ assertNull(diffs.addTransition);
+ }
+
+ @Test
+ public void testA10MergeLtR3UseCase3way1() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyLeftToRight(diffs.addOwnedRule,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddOwnedRule(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeLtR3UseCase3way2() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyLeftToRight(diffs.addOwnedRule,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteOwnedRule(comparison, diffs);
+ }
+
+ private void checkMergeDeleteOwnedRule(Comparison comparison, DiffsOfInterest diffs) {
+ assertEquals(NB_DIFFS - 3, comparison.getDifferences().size());
+ assertNull(diffs.addOwnedRule);
+ assertNull(diffs.addGuard);
+ assertNull(diffs.addPrecondition);
+ }
+
+ @Test
+ public void testA10MergeRtL1UseCase() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition).copyRightToLeft(
+ diffs.addPrecondition, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeletePrecondition(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL1UseCase3way1() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition).copyRightToLeft(
+ diffs.addPrecondition, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeletePrecondition(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL1UseCase3way2() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition).copyRightToLeft(
+ diffs.addPrecondition, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddPrecondition(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL2UseCase() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyRightToLeft(diffs.addGuard,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteGuard(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL2UseCase3way1() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyRightToLeft(diffs.addGuard,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteGuard(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL2UseCase3way2() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyRightToLeft(diffs.addGuard,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddGuard(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL3UseCase() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyRightToLeft(diffs.addOwnedRule,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteOwnedRule(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL3UseCase3way1() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyRightToLeft(diffs.addOwnedRule,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeDeleteOwnedRule(comparison, diffs);
+ }
+
+ @Test
+ public void testA10MergeRtL3UseCase3way2() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyRightToLeft(diffs.addOwnedRule,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.ADD);
+
+ checkMergeAddOwnedRule(comparison, diffs);
+ }
+
+ @Test
+ public void testA11UseCase() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right);
+ testAB1(TestKind.DELETE, comparison);
+ }
+
+ @Test
+ // local DELETE
+ public void testA11UseCase3way1() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right, right);
+ testAB1(TestKind.DELETE, comparison);
+ }
+
+ @Test
+ // remote DELETE
+ public void testA11UseCase3way2() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right, left);
+ testAB1(TestKind.DELETE, comparison);
+ }
+
+ @Test
+ public void testA11MergeLtR1UseCase() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition).copyLeftToRight(
+ diffs.addPrecondition, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeletePrecondition(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR1UseCase3way1() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition).copyLeftToRight(
+ diffs.addPrecondition, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeletePrecondition(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR1UseCase3way2() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition).copyLeftToRight(
+ diffs.addPrecondition, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddPrecondition(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR2UseCase() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyLeftToRight(diffs.addGuard,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteGuard(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR2UseCase3way1() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyLeftToRight(diffs.addGuard,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteGuard(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR2UseCase3way2() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyLeftToRight(diffs.addGuard,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddGuard(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR3UseCase() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyLeftToRight(diffs.addOwnedRule,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteOwnedRule(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR3UseCase3way1() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyLeftToRight(diffs.addOwnedRule,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteOwnedRule(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeLtR3UseCase3way2() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyLeftToRight(diffs.addOwnedRule,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddOwnedRule(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL1UseCase() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition).copyRightToLeft(
+ diffs.addPrecondition, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddPrecondition(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL1UseCase3way1() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition).copyRightToLeft(
+ diffs.addPrecondition, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddPrecondition(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL1UseCase3way2() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition).copyRightToLeft(
+ diffs.addPrecondition, new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeletePrecondition(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL2UseCase() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyRightToLeft(diffs.addGuard,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddGuard(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL2UseCase3way1() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyRightToLeft(diffs.addGuard,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddGuard(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL2UseCase3way2() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyRightToLeft(diffs.addGuard,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteGuard(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL3UseCase() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyRightToLeft(diffs.addOwnedRule,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddOwnedRule(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL3UseCase3way1() throws IOException {
+ final Resource left = input.getA2Right();
+ final Resource right = input.getA2Left();
+
+ Comparison comparison = compare(left, right, right);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyRightToLeft(diffs.addOwnedRule,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeAddOwnedRule(comparison, diffs);
+ }
+
+ @Test
+ public void testA11MergeRtL3UseCase3way2() throws IOException {
+ final Resource left = input.getA2Left();
+ final Resource right = input.getA2Right();
+
+ Comparison comparison = compare(left, right, left);
+
+ DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE);
+
+ // ** MERGE **
+ getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyRightToLeft(diffs.addOwnedRule,
+ new BasicMonitor());
+
+ comparison = compare(left, right);
+ diffs = getDiffs(comparison, TestKind.DELETE);
+
+ checkMergeDeleteOwnedRule(comparison, diffs);
+ }
+
+ private void testAB1(TestKind kind, final Comparison comparison) {
+ final List<Diff> differences = comparison.getDifferences();
+
+ assertSame(Integer.valueOf(NB_DIFFS), Integer.valueOf(differences.size()));
+
+ DiffsOfInterest diffs = getDiffs(comparison, kind);
+
+ if (kind.equals(TestKind.DELETE)) {
+ assertEquals(0, diffs.addPrecondition.getImplies().size());
+ assertEquals(1, diffs.addPrecondition.getImpliedBy().size());
+ assertTrue(diffs.addPrecondition.getImpliedBy().contains(diffs.addGuard));
+
+ assertEquals(1, diffs.addGuard.getImplies().size());
+ assertTrue(diffs.addGuard.getImplies().contains(diffs.addPrecondition));
+ assertEquals(1, diffs.addGuard.getImpliedBy().size());
+ assertTrue(diffs.addGuard.getImpliedBy().contains(diffs.addOwnedRule));
+
+ assertEquals(1, diffs.addOwnedRule.getImplies().size());
+ assertTrue(diffs.addOwnedRule.getImplies().contains(diffs.addGuard));
+ assertEquals(0, diffs.addOwnedRule.getImpliedBy().size());
+ } else {
+ assertEquals(1, diffs.addPrecondition.getImplies().size());
+ assertTrue(diffs.addPrecondition.getImplies().contains(diffs.addGuard));
+ assertEquals(0, diffs.addPrecondition.getImpliedBy().size());
+
+ assertEquals(1, diffs.addGuard.getImplies().size());
+ assertTrue(diffs.addGuard.getImplies().contains(diffs.addOwnedRule));
+ assertEquals(1, diffs.addGuard.getImpliedBy().size());
+ assertTrue(diffs.addGuard.getImpliedBy().contains(diffs.addPrecondition));
+
+ assertEquals(0, diffs.addOwnedRule.getImplies().size());
+ assertEquals(1, diffs.addOwnedRule.getImpliedBy().size());
+ assertTrue(diffs.addOwnedRule.getImpliedBy().contains(diffs.addGuard));
+ }
+
+ }
+
+ @Override
+ protected AbstractInputData getInput() {
+ return input;
+ }
+
+ private class DiffsOfInterest {
+ public Diff addTransition;
+
+ public Diff addPrecondition;
+
+ public Diff addOwnedRule;
+
+ public Diff addGuard;
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/ImplicationsInputData.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/ImplicationsInputData.java
new file mode 100644
index 000000000..05471387f
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/ImplicationsInputData.java
@@ -0,0 +1,41 @@
+package org.eclipse.emf.compare.uml2.tests.implications.data;
+
+import java.io.IOException;
+
+import org.eclipse.emf.compare.tests.framework.AbstractInputData;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.uml2.uml.resources.util.UMLResourcesUtil;
+
+public class ImplicationsInputData extends AbstractInputData {
+ public Resource getA1Left() throws IOException {
+ return loadFromClassLoader("a1/left.uml", createResourceSet()); //$NON-NLS-1$
+ }
+
+ public Resource getA1Right() throws IOException {
+ return loadFromClassLoader("a1/right.uml", createResourceSet()); //$NON-NLS-1$
+ }
+
+ public Resource getA2Left() throws IOException {
+ return loadFromClassLoader("a2/left.uml", createResourceSet()); //$NON-NLS-1$
+ }
+
+ public Resource getA2Right() throws IOException {
+ return loadFromClassLoader("a2/right.uml", createResourceSet()); //$NON-NLS-1$
+ }
+
+ public Resource getA3Left() throws IOException {
+ return loadFromClassLoader("a3/left.uml", createResourceSet()); //$NON-NLS-1$
+ }
+
+ public Resource getA3Right() throws IOException {
+ return loadFromClassLoader("a3/right.uml", createResourceSet()); //$NON-NLS-1$
+ }
+
+ private ResourceSet createResourceSet() {
+ final ResourceSet resourceSet = new ResourceSetImpl();
+ UMLResourcesUtil.init(resourceSet);
+ return resourceSet;
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a1/left.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a1/left.uml
new file mode 100644
index 000000000..f3673bd07
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a1/left.uml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmlns:uml="http://www.eclipse.org/uml2/4.0.0/UML" xmi:id="_Wo9kcV9kEeC2jdN7B1dxQw" name="myModel">
+ <packagedElement xmi:type="uml:Class" xmi:id="_eOr_sF9kEeC2jdN7B1dxQw" name="Class1"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_epJuIF9kEeC2jdN7B1dxQw" name="Class2"/>
+ <packagedElement xmi:type="uml:Association" xmi:id="_n8aCMF9kEeC2jdN7B1dxQw" name="class1sToClass2s" memberEnd="_n8bQUF9kEeC2jdN7B1dxQw _n8e6sF9kEeC2jdN7B1dxQw" navigableOwnedEnd="_n8bQUF9kEeC2jdN7B1dxQw _n8e6sF9kEeC2jdN7B1dxQw">
+ <ownedEnd xmi:id="_n8bQUF9kEeC2jdN7B1dxQw" name="class1s" type="_eOr_sF9kEeC2jdN7B1dxQw" association="_n8aCMF9kEeC2jdN7B1dxQw">
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_n8dskF9kEeC2jdN7B1dxQw"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_n8eToF9kEeC2jdN7B1dxQw" value="*"/>
+ </ownedEnd>
+ <ownedEnd xmi:id="_n8e6sF9kEeC2jdN7B1dxQw" name="class2s" type="_epJuIF9kEeC2jdN7B1dxQw" association="_n8aCMF9kEeC2jdN7B1dxQw">
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_n8gv4F9kEeC2jdN7B1dxQw"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_n8hW8F9kEeC2jdN7B1dxQw" value="*"/>
+ </ownedEnd>
+ </packagedElement>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a1/right.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a1/right.uml
new file mode 100644
index 000000000..ccc31d41c
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a1/right.uml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmlns:uml="http://www.eclipse.org/uml2/4.0.0/UML" xmi:id="_Wo9kcV9kEeC2jdN7B1dxQw" name="myModel">
+ <packagedElement xmi:type="uml:Class" xmi:id="_eOr_sF9kEeC2jdN7B1dxQw" name="Class1"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_epJuIF9kEeC2jdN7B1dxQw" name="Class2"/>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a2/left.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a2/left.uml
new file mode 100644
index 000000000..e75d3ce82
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a2/left.uml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20110701" xmlns:xmi="http://www.omg.org/spec/XMI/20110701" xmlns:uml="http://www.eclipse.org/uml2/4.0.0/UML" xmi:id="_gJeW8NfvEeKprMYB98qQlQ" name="model">
+ <packagedElement xmi:type="uml:StateMachine" xmi:id="_gM6FcNfvEeKprMYB98qQlQ" name="StateMachine0">
+ <region xmi:id="_gM6FcdfvEeKprMYB98qQlQ" name="Region0">
+ <transition xmi:type="uml:ProtocolTransition" xmi:id="_LphrgNfwEeKprMYB98qQlQ" name="transition1" guard="_aigAANfyEeKprMYB98qQlQ" preCondition="_aigAANfyEeKprMYB98qQlQ">
+ <ownedRule xmi:id="_aigAANfyEeKprMYB98qQlQ" name="rule1"/>
+ <ownedRule xmi:id="_fWcQINfyEeKprMYB98qQlQ" name="rule2"/>
+ <ownedRule xmi:id="_g76ZINfyEeKprMYB98qQlQ" name="guard1"/>
+ </transition>
+ <subvertex xmi:type="uml:State" xmi:id="_jgDRMNfvEeKprMYB98qQlQ" name="State0"/>
+ <subvertex xmi:type="uml:State" xmi:id="_lFPGUNfvEeKprMYB98qQlQ" name="State1"/>
+ </region>
+ </packagedElement>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a2/right.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a2/right.uml
new file mode 100644
index 000000000..573b4533a
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a2/right.uml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20110701" xmlns:xmi="http://www.omg.org/spec/XMI/20110701" xmlns:uml="http://www.eclipse.org/uml2/4.0.0/UML" xmi:id="_gJeW8NfvEeKprMYB98qQlQ" name="model">
+ <packagedElement xmi:type="uml:StateMachine" xmi:id="_gM6FcNfvEeKprMYB98qQlQ" name="StateMachine0">
+ <region xmi:id="_gM6FcdfvEeKprMYB98qQlQ" name="Region0">
+ <subvertex xmi:type="uml:State" xmi:id="_jgDRMNfvEeKprMYB98qQlQ" name="State0"/>
+ <subvertex xmi:type="uml:State" xmi:id="_lFPGUNfvEeKprMYB98qQlQ" name="State1"/>
+ </region>
+ </packagedElement>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a3/left.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a3/left.uml
new file mode 100644
index 000000000..f93c9a32b
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a3/left.uml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmlns:uml="http://www.eclipse.org/uml2/4.0.0/UML" xmi:id="_SSnEIIYEEeC_LdOTKS1r7g" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_WNoqEYYWEeCV1bmJqi-tSQ" clientDependency="_epYHUIYWEeCV1bmJqi-tSQ _I1OzkNgfEeKUpal9fab9XA" name="Class0">
+ <substitution xmi:id="_I1OzkNgfEeKUpal9fab9XA" name="substitution1" client="_WNoqEYYWEeCV1bmJqi-tSQ" supplier="_XMJgwIYWEeCV1bmJqi-tSQ"/>
+ <interfaceRealization xmi:id="_epYHUIYWEeCV1bmJqi-tSQ" name="InterfaceRealization0" client="_WNoqEYYWEeCV1bmJqi-tSQ" supplier="_XMJgwIYWEeCV1bmJqi-tSQ" contract="_XMJgwIYWEeCV1bmJqi-tSQ"/>
+ </packagedElement>
+ <packagedElement xmi:type="uml:Interface" xmi:id="_XMJgwIYWEeCV1bmJqi-tSQ" name="Interface0"/>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a3/right.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a3/right.uml
new file mode 100644
index 000000000..d2b1a2ecc
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/data/a3/right.uml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmlns:uml="http://www.eclipse.org/uml2/4.0.0/UML" xmi:id="_SSnEIIYEEeC_LdOTKS1r7g" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_WNoqEYYWEeCV1bmJqi-tSQ" name="Class0"/>
+ <packagedElement xmi:type="uml:Interface" xmi:id="_XMJgwIYWEeCV1bmJqi-tSQ" name="Interface0"/>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/suite/AllTests.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/suite/AllTests.java
index e2a648b22..35b5666b2 100644
--- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/suite/AllTests.java
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/suite/AllTests.java
@@ -31,6 +31,9 @@ import org.eclipse.emf.compare.uml2.tests.executionSpecification.AddActionExecut
import org.eclipse.emf.compare.uml2.tests.executionSpecification.AddBehaviorExecutionSpecificationTest;
import org.eclipse.emf.compare.uml2.tests.extend.AddExtendTest;
import org.eclipse.emf.compare.uml2.tests.generalizationSet.AddGeneralizationSetTest;
+import org.eclipse.emf.compare.uml2.tests.implications.ImplicationsAssociationTest;
+import org.eclipse.emf.compare.uml2.tests.implications.ImplicationsInterfaceRealizationTest;
+import org.eclipse.emf.compare.uml2.tests.implications.ImplicationsTransitionTest;
import org.eclipse.emf.compare.uml2.tests.include.AddIncludeTest;
import org.eclipse.emf.compare.uml2.tests.merge.ExtensionMergeTest;
import org.eclipse.emf.compare.uml2.tests.message.AddMessageTest;
@@ -55,7 +58,8 @@ import org.junit.runners.Suite.SuiteClasses;
AddSubstitutionTest.class, AddUsageTest.class, AddMessageTest.class,
AddActionExecutionSpecificationTest.class, AddBehaviorExecutionSpecificationTest.class,
AddIncludeTest.class, AddTimeConstraintTest.class, ProfileTest.class, DynamicStereotypeTest.class,
- StaticStereotypeTest.class })
+ StaticStereotypeTest.class, ImplicationsAssociationTest.class, ImplicationsTransitionTest.class,
+ ImplicationsInterfaceRealizationTest.class })
public class AllTests {
/**
diff --git a/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/UMLPostProcessor.java b/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/UMLPostProcessor.java
index 7259a3645..b5b712aab 100644
--- a/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/UMLPostProcessor.java
+++ b/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/UMLPostProcessor.java
@@ -10,68 +10,36 @@
*******************************************************************************/
package org.eclipse.emf.compare.uml2.internal.postprocessor;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-import com.google.common.primitives.Ints;
+import static org.eclipse.emf.compare.internal.utils.ComparisonUtil.isAddOrSetDiff;
+import static org.eclipse.emf.compare.internal.utils.ComparisonUtil.isDeleteOrUnsetDiff;
-import java.lang.reflect.Field;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.util.Monitor;
import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.Diff;
-import org.eclipse.emf.compare.DifferenceKind;
-import org.eclipse.emf.compare.DifferenceSource;
import org.eclipse.emf.compare.Match;
import org.eclipse.emf.compare.ReferenceChange;
import org.eclipse.emf.compare.internal.postprocessor.factories.IChangeFactory;
import org.eclipse.emf.compare.postprocessor.IPostProcessor;
import org.eclipse.emf.compare.uml2.internal.UMLDiff;
import org.eclipse.emf.compare.uml2.internal.postprocessor.extension.UMLExtensionFactoryRegistry;
-import org.eclipse.emf.compare.utils.ReferenceUtil;
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.util.EcoreUtil;
-import org.eclipse.uml2.common.util.SubsetSupersetEObjectEList;
+import org.eclipse.emf.compare.uml2.internal.postprocessor.util.UMLCompareUtil;
+import org.eclipse.emf.ecore.EReference;
+/**
+ * Post-processor to create the UML difference extensions.
+ *
+ * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
+ */
public class UMLPostProcessor implements IPostProcessor {
/** UML2 extensions factories. */
private Set<IChangeFactory> uml2ExtensionFactories;
/**
- * UML has notions of "subset" and "superset" features, which can be multiply derived but can also hold
- * values of their own.
- * <p>
- * For example, Association#memberEnds is a superset of Association#ownedEnds which in turn is a superset
- * of Association#navigableOwnedEnds.
- * </p>
- * <p>
- * If we add a value to "ownedEnds", it will automatically be added to "memberEnds" but not to
- * "navigableOwnedEnds". EMF Compare will detect two differences : 'value has been added to ownedEnds' and
- * 'value has been added to memberEnds'. We need to ignore the diff on memberEnds, but not the one on
- * ownedEnds (otherwise, and since these are not simple equivalences, the value would be added twice to
- * memberEnds, and once in ownedEnds).
- * </p>
- * <p>
- * Likewise, if we add a value to navigableOwnedEnds, we must still ignore the diff on memberEnds, but
- * this time and for that value we also need to ignore the diff on ownedEnds, lest we end up post-merge
- * with three identical values in memberEnds, two in ownedEnds and one in navigableOwnedEnds.
- * </p>
- * <p>
- * Since there is no API way to determine which references are subsets of another, we will have to resort
- * to casting the reference's value in {@link SubsetSupersetEObjectEList} and reflexively access its
- * "subsetFeatureIDs" protected field.
- * </p>
- */
- private static final Field SUBSET_FEATURES_FIELD = getSubsetField();
-
- /**
* {@inheritDoc}
*
* @see org.eclipse.emf.compare.postprocessor.IPostProcessor#postMatch(org.eclipse.emf.compare.Comparison,
@@ -91,101 +59,6 @@ public class UMLPostProcessor implements IPostProcessor {
// Not needed here.
}
- private void removeDuplicateDiffs(Comparison comparison) {
- final Set<Diff> removeMe = Sets.newLinkedHashSet();
- for (Diff input : comparison.getDifferences()) {
- if (!(input instanceof ReferenceChange && ((ReferenceChange)input).getReference().isMany())) {
- // Nothing to see here
- continue;
- }
-
- final EObject matchSide = getSourceSide(input);
- final Object value = ReferenceUtil.safeEGet(matchSide, ((ReferenceChange)input).getReference());
- // The only diffs that can be duplicated are those that can have subsets
- if (value instanceof SubsetSupersetEObjectEList<?>) {
- final int[] subsetsFeatures = getSubsetFeatures((SubsetSupersetEObjectEList<?>)value);
-
- // If we have subsets and this is a MOVE, ignore the Diff altogether
- if (subsetsFeatures.length > 0 && input.getKind() == DifferenceKind.MOVE) {
- removeMe.add(input);
- } else {
- // Check each subset : if it contains the same value as the input then it is a duplicate
- final Diff duplicate = findDuplicatedDiffOnLowestSubset(input, matchSide, subsetsFeatures);
- if (duplicate != null) {
- // We have a duplicate on a subset. This diff will be removed from the comparison
- // model, but before that we need to copy all of its requires and refines
- removeMe.add(input);
- copyRequirements(input, duplicate);
- }
- }
- }
- }
-
- for (Diff sentenced : removeMe) {
- EcoreUtil.delete(sentenced);
- }
- }
-
- private void copyRequirements(Diff source, Diff target) {
- for (Diff requiredBy : source.getRequiredBy()) {
- if (requiredBy != target) {
- target.getRequiredBy().add(requiredBy);
- }
- }
- for (Diff requires : source.getRequires()) {
- if (requires != target) {
- target.getRequires().add(requires);
- }
- }
- if (source.getEquivalence() != null) {
- source.getEquivalence().getDifferences().add(target);
- }
- }
-
- private Diff findDuplicatedDiffOnLowestSubset(Diff input, EObject matchSide, int[] subsetsFeatures) {
- final EClass clazz = matchSide.eClass();
- final Object diffValue = ((ReferenceChange)input).getValue();
- final int[] actualIDs = convertFeatureIDs(clazz, subsetsFeatures);
-
- Diff lowestDuplicate = null;
- final Iterator<ReferenceChange> siblings = Iterables.filter(input.getMatch().getDifferences(),
- ReferenceChange.class).iterator();
- while (siblings.hasNext() && lowestDuplicate == null) {
- final ReferenceChange sibling = siblings.next();
- final int refID = sibling.getReference().getFeatureID();
- final Object siblingValue = sibling.getValue();
-
- if (sibling.getKind() == input.getKind() && Ints.contains(actualIDs, refID)
- && siblingValue == diffValue) {
- // This is a duplicate... but it may be a duplicate itself.
- // We have to go down to the lowest level.
- final Object subset = matchSide.eGet(clazz.getEStructuralFeature(refID), false);
- if (subset instanceof SubsetSupersetEObjectEList<?>) {
- final int[] lowerSubsets = getSubsetFeatures((SubsetSupersetEObjectEList<?>)subset);
- final Diff lowerDuplicate = findDuplicatedDiffOnLowestSubset(sibling, matchSide,
- lowerSubsets);
- if (lowerDuplicate != null) {
- lowestDuplicate = lowerDuplicate;
- } else {
- lowestDuplicate = sibling;
- }
- } else {
- lowestDuplicate = sibling;
- }
- }
- }
-
- return lowestDuplicate;
- }
-
- private int[] convertFeatureIDs(EClass clazz, int[] ids) {
- int[] result = new int[ids.length];
- for (int i = 0; i < ids.length; i++) {
- result[i] = clazz.getEStructuralFeature(ids[i]).getFeatureID();
- }
- return result;
- }
-
/**
* {@inheritDoc}
*
@@ -222,7 +95,6 @@ public class UMLPostProcessor implements IPostProcessor {
* org.eclipse.emf.common.util.Monitor)
*/
public void postComparison(Comparison comparison, Monitor monitor) {
- removeDuplicateDiffs(comparison);
final Map<Class<? extends Diff>, IChangeFactory> mapUml2ExtensionFactories = UMLExtensionFactoryRegistry
.createExtensionFactories();
@@ -243,6 +115,14 @@ public class UMLPostProcessor implements IPostProcessor {
}
}
}
+
+ // Filling implications with subsets
+ for (Diff diff : comparison.getDifferences()) {
+ if (diff instanceof ReferenceChange) {
+ fillImplicationsWithUMLSubsets((ReferenceChange)diff);
+ }
+ }
+
}
/**
@@ -250,8 +130,6 @@ public class UMLPostProcessor implements IPostProcessor {
*
* @param element
* The input {@link DiffElement}.
- * @param diffModelCrossReferencer
- * The cross referencer.
*/
private void applyManagedTypes(Diff element) {
for (IChangeFactory factory : uml2ExtensionFactories) {
@@ -273,80 +151,29 @@ public class UMLPostProcessor implements IPostProcessor {
}
/**
- * Retrieves the value of the <i>subsetFeatureIDs</i> field of the given list. Note that this will never
- * return <code>null</code>, but an empty array instead.
+ * Fill the implication links ({@link Diff#getImplies()}, {@link Diff#getImpliedBy()}) on the given
+ * reference change.
*
- * @param list
- * The list for which we need the subset feature IDs.
- * @return The IDs of the subsets from which the given lists derives its values.
- * @see #SUBSET_FEATURES_FIELD
+ * @param diff
+ * The reference change.
*/
- private static int[] getSubsetFeatures(SubsetSupersetEObjectEList<?> list) {
- Object value = null;
- try {
- value = SUBSET_FEATURES_FIELD.get(list);
- } catch (IllegalArgumentException e) {
- // Ignore, cannot happen
- } catch (IllegalAccessException e) {
- // Ignore, cannot happen
- }
- if (value instanceof int[]) {
- return (int[])value;
- }
- return new int[0];
- }
-
- /**
- * This will allow us to retrieve the "subsetFeatureIDs" protected field of the
- * {@link SubsetSupersetEObjectEList} class and set it accessible for further reflexive access. More on
- * this on the {@link #SUBSET_FEATURES_FIELD field}'s description.
- *
- * @return The {@link SubsetSupersetEObjectEList#subsetFeatureIDs} field, after having made it accessible.
- * @see #SUBSET_FEATURES_FIELD
- */
- private static Field getSubsetField() {
- try {
- final Field subsetIDs = SubsetSupersetEObjectEList.class.getDeclaredField("subsetFeatureIDs"); //$NON-NLS-1$
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- subsetIDs.setAccessible(true);
- return null;
+ private void fillImplicationsWithUMLSubsets(ReferenceChange diff) {
+ EReference reference = diff.getReference();
+ // ADD implies ADD on non union supersets
+ // DELETE is implied by DEL on non union supersets
+ for (EReference superSet : UMLCompareUtil.getNonUnionSupersetReferences(reference)) {
+ Comparison comparison = diff.getMatch().getComparison();
+ for (Diff superSetDiff : comparison.getDifferences(superSet)) {
+ if (superSetDiff instanceof ReferenceChange
+ && ((ReferenceChange)superSetDiff).getReference() == superSet
+ && ((ReferenceChange)superSetDiff).getValue() == diff.getValue()) {
+ if (isAddOrSetDiff(diff) && isAddOrSetDiff(superSetDiff)) {
+ diff.getImplies().add(superSetDiff);
+ } else if (isDeleteOrUnsetDiff(diff) && isDeleteOrUnsetDiff(superSetDiff)) {
+ diff.getImpliedBy().add(superSetDiff);
+ }
}
- });
- return subsetIDs;
- } catch (SecurityException e) {
- // Ignore, cannot happen
- } catch (NoSuchFieldException e) {
- // Ignore, cannot happen
- }
- return null;
- }
-
- /**
- * Retrieves the EObject holding the reference on which we detected a difference.
- *
- * @param input
- * The difference for which we need a "holder" object.
- * @return The EObject holding the reference on which we detected a difference.
- */
- private static EObject getSourceSide(Diff input) {
- // Note that we know this diff is not a "CHANGE" as its reference is multi-valued
- final Match match = input.getMatch();
- final EObject matchSide;
- if (input.getKind() == DifferenceKind.DELETE) {
- if (match.getOrigin() != null) {
- matchSide = match.getOrigin();
- } else if (input.getSource() == DifferenceSource.LEFT) {
- matchSide = match.getRight();
- } else {
- // Should never happen
- matchSide = match.getLeft();
}
- } else if (input.getSource() == DifferenceSource.LEFT) {
- matchSide = match.getLeft();
- } else {
- matchSide = match.getRight();
}
- return matchSide;
}
}
diff --git a/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/util/UMLCompareUtil.java b/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/util/UMLCompareUtil.java
index e5c32c58d..59e6aa81f 100644
--- a/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/util/UMLCompareUtil.java
+++ b/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/util/UMLCompareUtil.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012 Obeo.
+ * Copyright (c) 2013 Obeo.
* 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
@@ -10,8 +10,15 @@
*******************************************************************************/
package org.eclipse.emf.compare.uml2.internal.postprocessor.util;
-import org.eclipse.emf.ecore.EClass;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+
+import java.util.Collections;
+import java.util.Iterator;
+
+import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Extension;
@@ -22,7 +29,12 @@ import org.eclipse.uml2.uml.util.UMLUtil;
*
* @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a>
*/
-public class UMLCompareUtil {
+public final class UMLCompareUtil {
+
+ /** Constructor. */
+ private UMLCompareUtil() {
+ }
+
/**
* Retrieves the base element for the specified stereotype application, i.e. the element to which the
* stereotype is applied.
@@ -37,25 +49,83 @@ public class UMLCompareUtil {
* @return The base element.
*/
public static Element getBaseElement(EObject stereotypeApplication) {
+ if (stereotypeApplication == null) {
+ return null;
+ }
+
Element baseElement = UMLUtil.getBaseElement(stereotypeApplication);
- if (baseElement == null) {
- if (stereotypeApplication != null) {
- EClass eClass = stereotypeApplication.eClass();
- for (EStructuralFeature eStructuralFeature : eClass.getEAllStructuralFeatures()) {
+ final Iterator<EStructuralFeature> features = stereotypeApplication.eClass()
+ .getEAllStructuralFeatures().iterator();
+ while (features.hasNext() && baseElement == null) {
+ final EStructuralFeature feature = features.next();
+ if (feature.getName().startsWith(Extension.METACLASS_ROLE_PREFIX)) {
+ final Object value = stereotypeApplication.eGet(feature);
+ if (value instanceof Element) {
+ baseElement = (Element)value;
+ }
+ }
+ }
+
+ return baseElement;
+ }
+
+ /**
+ * From the given EReference, it returns the list of EReference which are superset and non union.
+ *
+ * @param reference
+ * The EReference subset from which is requested the non union superset.
+ * @return The list of EReference non union superset.
+ */
+ public static Iterable<EReference> getNonUnionSupersetReferences(EReference reference) {
+ return Iterables.filter(getSupersetReferences(reference), isNonUnionReference());
+ }
- if (eStructuralFeature.getName().startsWith(Extension.METACLASS_ROLE_PREFIX)) {
+ private static Predicate<? super EReference> isNonUnionReference() {
+ return new Predicate<EReference>() {
+ public boolean apply(EReference input) {
+ return input != null
+ && !Iterables.any(input.getEAnnotations(), UMLUtilForCompare.isUnionAnnotation());
+ }
+ };
+ }
- Object value = stereotypeApplication.eGet(eStructuralFeature);
+ /**
+ * From the given EReference, it returns the list of EReference which are superset.
+ *
+ * @param reference
+ * The EReference subset from which is requested the superset.
+ * @return The list of EReference superset.
+ */
+ private static Iterable<EReference> getSupersetReferences(EReference reference) {
+ EAnnotation subsetsAnnotation = Iterables.find(reference.getEAnnotations(), UMLUtilForCompare
+ .isSubsetsAnnotation(), null);
+ if (subsetsAnnotation != null) {
+ return Iterables.filter(subsetsAnnotation.getReferences(), EReference.class);
+ }
+ return Collections.emptyList();
+ }
- if (value instanceof Element) {
- return (Element)value;
- }
- }
+ /**
+ * This extends UMLUtil to get the name of the used annotations for subsets and unions.
+ *
+ * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
+ */
+ private static class UMLUtilForCompare extends UMLUtil {
+ public static Predicate<? super EAnnotation> isSubsetsAnnotation() {
+ return new Predicate<EAnnotation>() {
+ public boolean apply(EAnnotation input) {
+ return input != null && input.getSource().equals(ANNOTATION__SUBSETS);
}
- }
+ };
}
- return baseElement;
+ public static Predicate<? super EAnnotation> isUnionAnnotation() {
+ return new Predicate<EAnnotation>() {
+ public boolean apply(EAnnotation input) {
+ return input != null && input.getSource().equals(ANNOTATION__UNION);
+ }
+ };
+ }
}
}
diff --git a/plugins/org.eclipse.emf.compare/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.compare/META-INF/MANIFEST.MF
index 939f2f939..6f1c8b284 100644
--- a/plugins/org.eclipse.emf.compare/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.compare/META-INF/MANIFEST.MF
@@ -15,6 +15,11 @@ Export-Package: org.eclipse.emf.compare,
org.eclipse.emf.compare.internal;x-friends:="org.eclipse.emf.compare.logical,org.eclipse.emf.compare.ide",
org.eclipse.emf.compare.internal.postprocessor.factories;x-internal:=true,
org.eclipse.emf.compare.internal.spec;x-friends:="org.eclipse.emf.compare.tests",
+ org.eclipse.emf.compare.internal.utils;
+ x-friends:="org.eclipse.emf.compare.ide.ui,
+ org.eclipse.emf.compare.tests,
+ org.eclipse.emf.compare.uml2,
+ org.eclipse.emf.compare.diagram.ide.ui",
org.eclipse.emf.compare.match,
org.eclipse.emf.compare.match.eobject,
org.eclipse.emf.compare.match.eobject.internal;x-internal:=true,
diff --git a/plugins/org.eclipse.emf.compare/model/compare.ecore b/plugins/org.eclipse.emf.compare/model/compare.ecore
index bcfbf848b..8a2399fff 100644
--- a/plugins/org.eclipse.emf.compare/model/compare.ecore
+++ b/plugins/org.eclipse.emf.compare/model/compare.ecore
@@ -1,393 +1,397 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="compare" nsURI="http://www.eclipse.org/emf/compare" nsPrefix="compare">
- <eClassifiers xsi:type="ecore:EClass" name="Comparison">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This will act as the &quot;root&quot; of a comparison. It will reference one match for every root of the input models, along with the differences detected for each of them."/>
- </eAnnotations>
- <eOperations name="getDifferences" upperBound="-1" eType="#//Diff">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Returns all differences contained by this Comparison and its children."/>
- </eAnnotations>
- </eOperations>
- <eOperations name="getDifferences" upperBound="-1" eType="#//Diff">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Returns all differences that reference the given EObject (for instance, all ReferenceChanges that reference the given EObject through the &quot;value&quot; EReference). &#xA;&lt;p>&#xA;To get differences detected on the given EObject or one of its counterpart in left, right or origin, you should call the following code:&#xA;&lt;pre>&#xA;Match match = getMatch(eObject);&#xA;if (match != null) {&#xA; differences = match.getDifferences();&#xA;}&#xA;&lt;/pre>"/>
- </eAnnotations>
- <eParameters name="element" eType="ecore:EClass platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EObject">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="The EObject for which we seek all related differences."/>
- </eAnnotations>
- </eParameters>
- </eOperations>
- <eOperations name="getMatch" eType="#//Match">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Finds and return the Match for the given EObject."/>
- </eAnnotations>
- <eParameters name="element" eType="ecore:EClass platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EObject">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="The EObject for which we seek the match."/>
- </eAnnotations>
- </eParameters>
- </eOperations>
- <eOperations name="getEqualityHelper" eType="#//IEqualityHelper"/>
- <eStructuralFeatures xsi:type="ecore:EReference" name="matchedResources" upperBound="-1"
- eType="#//MatchResource" containment="true" eOpposite="#//MatchResource/comparison">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This contains the mappings for each compared Resource."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="matches" upperBound="-1"
- eType="#//Match" containment="true">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This contains the match tree &quot;mimicking&quot; the input models' hierarchy."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="conflicts" upperBound="-1"
- eType="#//Conflict" containment="true">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="If we detected any conflict during the comparison process, this will contain them."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="equivalences" upperBound="-1"
- eType="#//Equivalence" containment="true">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="If we detected any equivalence between diffs during the comparison process, this will contain them."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EAttribute" name="threeWay" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean"/>
- </eClassifiers>
- <eClassifiers xsi:type="ecore:EClass" name="MatchResource">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="A MatchResource element represents the mapping between two or three resources : left, right, and their optional common ancestor. The resource will be identified through its URI."/>
- </eAnnotations>
- <eStructuralFeatures xsi:type="ecore:EAttribute" name="leftURI" lowerBound="1"
- eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Cannot be null. Represents the URI of the left resource of this mapping."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EAttribute" name="rightURI" lowerBound="1"
- eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Cannot be null. Represents the URI of the right resource of this mapping."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EAttribute" name="originURI" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This can be null in the case of two-way comparisons. If assigned, it will represent the URI of the origin resource for this mapping; the common ancestor of both others."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EAttribute" name="left" eType="ecore:EDataType platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EResource"
- transient="true">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Keeps a reference towards the left Resource of this Match. Might be null if this is a Comparison we have re-loaded from its serialized form and the left EResource could not be loaded."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EAttribute" name="right" eType="ecore:EDataType platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EResource"
- transient="true">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Keeps a reference towards the right Resource of this Match. Might be null if this is a Comparison we have re-loaded from its serialized form and the right EResource could not be loaded."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EAttribute" name="origin" eType="ecore:EDataType platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EResource"
- transient="true">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Keeps a reference towards the origin Resource of this Match. Might be null if this is a Comparison we have re-loaded from its serialized form and the origin EResource could not be loaded."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="comparison" eType="#//Comparison"
- eOpposite="#//Comparison/matchedResources"/>
- </eClassifiers>
- <eClassifiers xsi:type="ecore:EClass" name="Match">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="A MatchElement describes the mapping between the EObjects of two or three resources. This will reference all three of left, right and origin resources. However, note that instances of this class will also represent unmatched elements, in which case only one of either &quot;left&quot; or &quot;right&quot; will be assigned."/>
- </eAnnotations>
- <eOperations name="getComparison" eType="#//Comparison">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Finds and return the Comparison containing this Match."/>
- </eAnnotations>
- </eOperations>
- <eOperations name="getAllSubmatches">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Finds and returns all matches contained in this Match and its children, recursively."/>
- </eAnnotations>
- <eGenericType eClassifier="#//EIterable">
- <eTypeArguments eClassifier="#//Match"/>
- </eGenericType>
- </eOperations>
- <eOperations name="getAllDifferences">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Finds and returns all differences contained in this Match and its children, recursively."/>
- </eAnnotations>
- <eGenericType eClassifier="#//EIterable">
- <eTypeArguments eClassifier="#//Diff"/>
- </eGenericType>
- </eOperations>
- <eStructuralFeatures xsi:type="ecore:EReference" name="submatches" upperBound="-1"
- eType="#//Match" containment="true">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="The MatchElements will &quot;mimic&quot; the hierarchy of the input model(s). This containment feature will serve that purpose."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="differences" upperBound="-1"
- eType="#//Diff" containment="true" eOpposite="#//Diff/match">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This will contain the list of all differences pertaining to this mapping, if any."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="left" eType="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EObject">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This can be null in the case of unmatched elements in the right model. In all other cases, it will reference the left element of this mapping."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="right" eType="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EObject">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This can be null in the case of unmatched elements in the left model. In all other cases, it will reference the right element of this mapping."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="origin" eType="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EObject">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This can be null in the case of two-way comparisons, or unmatched elements that are only located in either left or right, i.e an element that was added since the origin, either in the left copy or the right one. In any other course of event, this will reference the origin element of this mapping."/>
- </eAnnotations>
- </eStructuralFeatures>
- </eClassifiers>
- <eClassifiers xsi:type="ecore:EClass" name="Diff">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="A DiffElement describes a difference related to the EObjects mapped by its parent MatchElement."/>
- </eAnnotations>
- <eOperations name="copyRightToLeft">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This will merge the diff from left to right."/>
- </eAnnotations>
- </eOperations>
- <eOperations name="copyLeftToRight">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This will merge the diff from right to left."/>
- </eAnnotations>
- </eOperations>
- <eOperations name="discard">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This will remove the diff from the model, effectively &quot;forgetting&quot; about it."/>
- </eAnnotations>
- </eOperations>
- <eStructuralFeatures xsi:type="ecore:EReference" name="match" lowerBound="1" eType="#//Match"
- eOpposite="#//Match/differences">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Back-reference towards this difference's parent match, it points towards the mapping on which this difference has been detected."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="requires" upperBound="-1"
- eType="#//Diff" eOpposite="#//Diff/requiredBy">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This will reference all differences that should be merged before this one."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="requiredBy" upperBound="-1"
- eType="#//Diff" eOpposite="#//Diff/requires">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This will reference all differences that depend on this one for their merging."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="refines" upperBound="-1"
- eType="#//Diff" eOpposite="#//Diff/refinedBy">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This can be used to create &quot;high level&quot; differences to regroup one or more diffs in a common &quot;container&quot;. For example, this could be used to regroup &lt;i>n&lt;/i> technical differences into one single semantic difference, such as the differences &quot;profile application added&quot; and &quot;reference to stereotype added&quot; that can actually be regrouped under a single, more understandable &quot;stereotype application added&quot;."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="refinedBy" upperBound="-1"
- eType="#//Diff" eOpposite="#//Diff/refines">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This will reference the higher-level difference that shadows this one, if any."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EAttribute" name="kind" lowerBound="1" eType="#//DifferenceKind">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Describes the kind of this difference, whether it is an addition, deletion, change, or move."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EAttribute" name="source" lowerBound="1"
- eType="#//DifferenceSource">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Returns the source of this diff, either one of DifferenceSource.LEFT (for two-way comparisons or differences detected between the left and origin elements) or DifferenceSource.RIGHT (for differences between the right and origin elements)."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EAttribute" name="state" lowerBound="1" eType="#//DifferenceState">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Returns the current state of this diff, either one of DifferenceState.UNRESOLVED (Diff is still in its initial state), DifferenceState.MERGED when the Diff has been merged or DifferenceState.DISCARDED if the user chose to ignore this difference."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="equivalence" eType="#//Equivalence"
- eOpposite="#//Equivalence/differences">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="If this diff is equivalent to another, we will reference the equivalence from here. For example, if a reference has an eOpposite, we will detect one diff for each side of the bidirectional reference, yet merging one of these diffs is enough. We consider them equivalent."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="conflict" eType="#//Conflict"
- eOpposite="#//Conflict/differences">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="If this element is in conflict with one (or more) other differences, this will reference the Conflict association."/>
- </eAnnotations>
- </eStructuralFeatures>
- </eClassifiers>
- <eClassifiers xsi:type="ecore:EClass" name="ResourceAttachmentChange" eSuperTypes="#//Diff">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This particular kind of difference describes the fragmentation (or un-fragmentation) of a model element in its own (or back in its parent's) resource."/>
- </eAnnotations>
- <eStructuralFeatures xsi:type="ecore:EAttribute" name="resourceURI" lowerBound="1"
- eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="URI of the resource in which the parent mapping's element is now located."/>
- </eAnnotations>
- </eStructuralFeatures>
- </eClassifiers>
- <eClassifiers xsi:type="ecore:EClass" name="ReferenceChange" eSuperTypes="#//Diff">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This particular kind of difference will be used to describe changes within a reference, whether the feature is multi-valued or not. In the case of a MOVE difference, this could actually mean two things : either the value has been moved from one index to another (moving the value at another position of the same reference), or the value has been moved from one container to another. This second case will only happen with containment references."/>
- </eAnnotations>
- <eStructuralFeatures xsi:type="ecore:EReference" name="reference" lowerBound="1"
- eType="ecore:EClass platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EReference">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="The reference in which &quot;something&quot; changed. If this difference is a MOVE from one reference to another, this will point towards the left reference."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="value" eType="ecore:EClass platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EObject">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="References the actual value on which a difference has been detected."/>
- </eAnnotations>
- </eStructuralFeatures>
- </eClassifiers>
- <eClassifiers xsi:type="ecore:EClass" name="AttributeChange" eSuperTypes="#//Diff">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This particular kind of difference will be used to describe changes within an attribute, whether the feature is multi-valued or not."/>
- </eAnnotations>
- <eStructuralFeatures xsi:type="ecore:EReference" name="attribute" lowerBound="1"
- eType="ecore:EClass platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EAttribute">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="The attribute in which &quot;something&quot; changed."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EAttribute" name="value" eType="ecore:EDataType platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EJavaObject">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="References the actual value on which a difference has been detected."/>
- </eAnnotations>
- </eStructuralFeatures>
- </eClassifiers>
- <eClassifiers xsi:type="ecore:EClass" name="Conflict">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Instances of this class describe conflicts between one or more differences in the left model as compared to differences in the right model. Conflicts can only happen in the case of three-way comparisons, when we have a common ancestor of both sides."/>
- </eAnnotations>
- <eOperations name="getLeftDifferences" lowerBound="1" upperBound="-1" eType="#//Diff">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This can be used to retrieve the list of differences that were made in the left element."/>
- </eAnnotations>
- </eOperations>
- <eOperations name="getRightDifferences" lowerBound="1" upperBound="-1" eType="#//Diff">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This can be used to retrieve the list of differences that were made in the right element."/>
- </eAnnotations>
- </eOperations>
- <eStructuralFeatures xsi:type="ecore:EAttribute" name="kind" lowerBound="1" eType="#//ConflictKind">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Describes the kind of this conflict, whether it is a real conflict or a pseudo-conflict."/>
- </eAnnotations>
- </eStructuralFeatures>
- <eStructuralFeatures xsi:type="ecore:EReference" name="differences" lowerBound="2"
- upperBound="-1" eType="#//Diff" eOpposite="#//Diff/conflict">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This will reference all differences that are related to this conflict. The number of elements contained in this list is &lt;u>at least&lt;/u> two."/>
- </eAnnotations>
- </eStructuralFeatures>
- </eClassifiers>
- <eClassifiers xsi:type="ecore:EClass" name="Equivalence">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Diffs are considered equivalent if merging one is enough to resolve both differences. For example, if a reference has an eOpposite, we will detect one diff for each side of the bidirectional reference, yet merging one of these diffs will automatically update the model in such a way that the second diff is &quot;merged&quot;."/>
- </eAnnotations>
- <eStructuralFeatures xsi:type="ecore:EReference" name="differences" lowerBound="2"
- upperBound="-1" eType="#//Diff" eOpposite="#//Diff/equivalence">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="References the &lt;i>n&lt;/i> diffs composing this equivalence. There are &lt;u>at least&lt;/u> two diffs in this list."/>
- </eAnnotations>
- </eStructuralFeatures>
- </eClassifiers>
- <eClassifiers xsi:type="ecore:EEnum" name="DifferenceKind">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="The differences detected through EMF Compare can be of 4 general types.&#xD;&#xA;&lt;ul>&#xD;&#xA;&#x9;&lt;li>ADD represent addition of model element or feature values,&lt;/li>&#xD;&#xA;&#x9;&lt;li>DELETE represent suppression of model element or feature values,&lt;/li>&#xD;&#xA;&#x9;&lt;li>CHANGE represent the modification of a feature value,&lt;/li>&#xD;&#xA;&#x9;&lt;li>MOVE will be used for difference on the containment feature of a model element, or differences on the order of a feature's values.&lt;/li>&#xD;&#xA;&lt;/ul>"/>
- </eAnnotations>
- <eLiterals name="ADD">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Represents the addition of model elements or feature values."/>
- </eAnnotations>
- </eLiterals>
- <eLiterals name="DELETE" value="1">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Represents the suppression of model elements or feature values."/>
- </eAnnotations>
- </eLiterals>
- <eLiterals name="CHANGE" value="2">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Represents the modification of a feature value."/>
- </eAnnotations>
- </eLiterals>
- <eLiterals name="MOVE" value="3">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Describes a difference on the containment feature of a model element, or differences on the order of a feature's values."/>
- </eAnnotations>
- </eLiterals>
- </eClassifiers>
- <eClassifiers xsi:type="ecore:EEnum" name="DifferenceSource">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This will be used to represent the source of a detected diff.&#xD;&#xA;&lt;ul>&#xD;&#xA;&#x9;&lt;li>LEFT if the difference has been detected between the left element and its origin,&lt;/li>&#xD;&#xA;&#x9;&lt;li>RIGHT if the difference has been detected between the right element and its origin.&lt;/li>&#xD;&#xA;&lt;/ul>&#xD;&#xA;&lt;b>Note&lt;/b> that differences detected during two-way comparisons will only be LEFT."/>
- </eAnnotations>
- <eLiterals name="LEFT">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Will be used if the difference has been detected between the left element and its origin. Differences detected during two-way comparisons will always have this has their source."/>
- </eAnnotations>
- </eLiterals>
- <eLiterals name="RIGHT" value="1">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Will be used if the difference has been detected between the right element and its origin."/>
- </eAnnotations>
- </eLiterals>
- </eClassifiers>
- <eClassifiers xsi:type="ecore:EEnum" name="DifferenceState">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="This will be used to represent the state of a detected diff.&#xD;&#xA;&lt;ul>&#xD;&#xA;&#x9;&lt;li>UNRESOLVED if the Diff is still in its initial state and the two sides differ,&lt;/li>&#xD;&#xA;&#x9;&lt;li>MERGED if the Diff has already been merged by the user,&lt;/li>&#xD;&#xA;&#x9;&lt;li>DISCARDED if the user chose to ignore this Diff.&lt;/li>&#xD;&#xA;&lt;/ul>"/>
- </eAnnotations>
- <eLiterals name="UNRESOLVED" literal="UNRESOLVED">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Indicates that the Diff is still in its initial state."/>
- </eAnnotations>
- </eLiterals>
- <eLiterals name="MERGED" value="1">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Indicates that the Diff has already been merged by the user."/>
- </eAnnotations>
- </eLiterals>
- <eLiterals name="DISCARDED" value="2" literal="DISCARDED">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Indicates that the user chose to ignore this Diff."/>
- </eAnnotations>
- </eLiterals>
- </eClassifiers>
- <eClassifiers xsi:type="ecore:EEnum" name="ConflictKind">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="Conflicts detected through EMF Compare can be of a number of different types.&#xD;&#xA;&lt;ul>&#xD;&#xA;&#x9;&lt;li>REAL are the conflicts that cannot be merged automatically,&lt;/li>&#xD;&#xA;&#x9;&lt;li>PSEUDO are the &quot;conflicts&quot; that represent the same change made on the two sides, which can thus be automatically merged.&lt;/li>&#xD;&#xA;&lt;/ul>"/>
- </eAnnotations>
- <eLiterals name="REAL">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="conflicts that cannot be merged automatically as they represent incompatible differences on the two sides."/>
- </eAnnotations>
- </eLiterals>
- <eLiterals name="PSEUDO" value="1">
- <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
- <details key="documentation" value="If the same change has been made on the two sides since the common ancestor, these changes will be marked as &quot;pseudo-conflicting&quot; changes : there are changes, but they can be merged automatically."/>
- </eAnnotations>
- </eLiterals>
- </eClassifiers>
- <eClassifiers xsi:type="ecore:EDataType" name="EIterable" instanceClassName="java.lang.Iterable">
- <eTypeParameters name="T"/>
- </eClassifiers>
- <eClassifiers xsi:type="ecore:EDataType" name="IEqualityHelper" instanceClassName="org.eclipse.emf.compare.utils.IEqualityHelper"
- serializable="false"/>
-</ecore:EPackage>
+<?xml version="1.0" encoding="UTF-8"?>
+<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="compare" nsURI="http://www.eclipse.org/emf/compare" nsPrefix="compare">
+ <eClassifiers xsi:type="ecore:EClass" name="Comparison">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This will act as the &quot;root&quot; of a comparison. It will reference one match for every root of the input models, along with the differences detected for each of them."/>
+ </eAnnotations>
+ <eOperations name="getDifferences" upperBound="-1" eType="#//Diff">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Returns all differences contained by this Comparison and its children."/>
+ </eAnnotations>
+ </eOperations>
+ <eOperations name="getDifferences" upperBound="-1" eType="#//Diff">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Returns all differences that reference the given EObject (for instance, all ReferenceChanges that reference the given EObject through the &quot;value&quot; EReference). &#xA;&lt;p>&#xA;To get differences detected on the given EObject or one of its counterpart in left, right or origin, you should call the following code:&#xA;&lt;pre>&#xA;Match match = getMatch(eObject);&#xA;if (match != null) {&#xA; differences = match.getDifferences();&#xA;}&#xA;&lt;/pre>"/>
+ </eAnnotations>
+ <eParameters name="element" eType="ecore:EClass platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EObject">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="The EObject for which we seek all related differences."/>
+ </eAnnotations>
+ </eParameters>
+ </eOperations>
+ <eOperations name="getMatch" eType="#//Match">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Finds and return the Match for the given EObject."/>
+ </eAnnotations>
+ <eParameters name="element" eType="ecore:EClass platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EObject">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="The EObject for which we seek the match."/>
+ </eAnnotations>
+ </eParameters>
+ </eOperations>
+ <eOperations name="getEqualityHelper" eType="#//IEqualityHelper"/>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="matchedResources" upperBound="-1"
+ eType="#//MatchResource" containment="true" eOpposite="#//MatchResource/comparison">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This contains the mappings for each compared Resource."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="matches" upperBound="-1"
+ eType="#//Match" containment="true">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This contains the match tree &quot;mimicking&quot; the input models' hierarchy."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="conflicts" upperBound="-1"
+ eType="#//Conflict" containment="true">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="If we detected any conflict during the comparison process, this will contain them."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="equivalences" upperBound="-1"
+ eType="#//Equivalence" containment="true">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="If we detected any equivalence between diffs during the comparison process, this will contain them."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="threeWay" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean"/>
+ </eClassifiers>
+ <eClassifiers xsi:type="ecore:EClass" name="MatchResource">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="A MatchResource element represents the mapping between two or three resources : left, right, and their optional common ancestor. The resource will be identified through its URI."/>
+ </eAnnotations>
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="leftURI" lowerBound="1"
+ eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Cannot be null. Represents the URI of the left resource of this mapping."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="rightURI" lowerBound="1"
+ eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Cannot be null. Represents the URI of the right resource of this mapping."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="originURI" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This can be null in the case of two-way comparisons. If assigned, it will represent the URI of the origin resource for this mapping; the common ancestor of both others."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="left" eType="ecore:EDataType platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EResource"
+ transient="true">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Keeps a reference towards the left Resource of this Match. Might be null if this is a Comparison we have re-loaded from its serialized form and the left EResource could not be loaded."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="right" eType="ecore:EDataType platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EResource"
+ transient="true">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Keeps a reference towards the right Resource of this Match. Might be null if this is a Comparison we have re-loaded from its serialized form and the right EResource could not be loaded."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="origin" eType="ecore:EDataType platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EResource"
+ transient="true">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Keeps a reference towards the origin Resource of this Match. Might be null if this is a Comparison we have re-loaded from its serialized form and the origin EResource could not be loaded."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="comparison" eType="#//Comparison"
+ eOpposite="#//Comparison/matchedResources"/>
+ </eClassifiers>
+ <eClassifiers xsi:type="ecore:EClass" name="Match">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="A MatchElement describes the mapping between the EObjects of two or three resources. This will reference all three of left, right and origin resources. However, note that instances of this class will also represent unmatched elements, in which case only one of either &quot;left&quot; or &quot;right&quot; will be assigned."/>
+ </eAnnotations>
+ <eOperations name="getComparison" eType="#//Comparison">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Finds and return the Comparison containing this Match."/>
+ </eAnnotations>
+ </eOperations>
+ <eOperations name="getAllSubmatches">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Finds and returns all matches contained in this Match and its children, recursively."/>
+ </eAnnotations>
+ <eGenericType eClassifier="#//EIterable">
+ <eTypeArguments eClassifier="#//Match"/>
+ </eGenericType>
+ </eOperations>
+ <eOperations name="getAllDifferences">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Finds and returns all differences contained in this Match and its children, recursively."/>
+ </eAnnotations>
+ <eGenericType eClassifier="#//EIterable">
+ <eTypeArguments eClassifier="#//Diff"/>
+ </eGenericType>
+ </eOperations>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="submatches" upperBound="-1"
+ eType="#//Match" containment="true">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="The MatchElements will &quot;mimic&quot; the hierarchy of the input model(s). This containment feature will serve that purpose."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="differences" upperBound="-1"
+ eType="#//Diff" containment="true" eOpposite="#//Diff/match">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This will contain the list of all differences pertaining to this mapping, if any."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="left" eType="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EObject">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This can be null in the case of unmatched elements in the right model. In all other cases, it will reference the left element of this mapping."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="right" eType="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EObject">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This can be null in the case of unmatched elements in the left model. In all other cases, it will reference the right element of this mapping."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="origin" eType="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EObject">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This can be null in the case of two-way comparisons, or unmatched elements that are only located in either left or right, i.e an element that was added since the origin, either in the left copy or the right one. In any other course of event, this will reference the origin element of this mapping."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ </eClassifiers>
+ <eClassifiers xsi:type="ecore:EClass" name="Diff">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="A DiffElement describes a difference related to the EObjects mapped by its parent MatchElement."/>
+ </eAnnotations>
+ <eOperations name="copyRightToLeft">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This will merge the diff from left to right."/>
+ </eAnnotations>
+ </eOperations>
+ <eOperations name="copyLeftToRight">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This will merge the diff from right to left."/>
+ </eAnnotations>
+ </eOperations>
+ <eOperations name="discard">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This will remove the diff from the model, effectively &quot;forgetting&quot; about it."/>
+ </eAnnotations>
+ </eOperations>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="match" lowerBound="1" eType="#//Match"
+ eOpposite="#//Match/differences">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Back-reference towards this difference's parent match, it points towards the mapping on which this difference has been detected."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="requires" upperBound="-1"
+ eType="#//Diff" eOpposite="#//Diff/requiredBy">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This will reference all differences that should be merged before this one."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="requiredBy" upperBound="-1"
+ eType="#//Diff" eOpposite="#//Diff/requires">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This will reference all differences that depend on this one for their merging."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="implies" upperBound="-1"
+ eType="#//Diff" eOpposite="#//Diff/impliedBy"/>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="impliedBy" upperBound="-1"
+ eType="#//Diff" eOpposite="#//Diff/implies"/>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="refines" upperBound="-1"
+ eType="#//Diff" eOpposite="#//Diff/refinedBy">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This can be used to create &quot;high level&quot; differences to regroup one or more diffs in a common &quot;container&quot;. For example, this could be used to regroup &lt;i>n&lt;/i> technical differences into one single semantic difference, such as the differences &quot;profile application added&quot; and &quot;reference to stereotype added&quot; that can actually be regrouped under a single, more understandable &quot;stereotype application added&quot;."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="refinedBy" upperBound="-1"
+ eType="#//Diff" eOpposite="#//Diff/refines">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This will reference the higher-level difference that shadows this one, if any."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="kind" lowerBound="1" eType="#//DifferenceKind">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Describes the kind of this difference, whether it is an addition, deletion, change, or move."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="source" lowerBound="1"
+ eType="#//DifferenceSource">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Returns the source of this diff, either one of DifferenceSource.LEFT (for two-way comparisons or differences detected between the left and origin elements) or DifferenceSource.RIGHT (for differences between the right and origin elements)."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="state" lowerBound="1" eType="#//DifferenceState">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Returns the current state of this diff, either one of DifferenceState.UNRESOLVED (Diff is still in its initial state), DifferenceState.MERGED when the Diff has been merged or DifferenceState.DISCARDED if the user chose to ignore this difference."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="equivalence" eType="#//Equivalence"
+ eOpposite="#//Equivalence/differences">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="If this diff is equivalent to another, we will reference the equivalence from here. For example, if a reference has an eOpposite, we will detect one diff for each side of the bidirectional reference, yet merging one of these diffs is enough. We consider them equivalent."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="conflict" eType="#//Conflict"
+ eOpposite="#//Conflict/differences">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="If this element is in conflict with one (or more) other differences, this will reference the Conflict association."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ </eClassifiers>
+ <eClassifiers xsi:type="ecore:EClass" name="ResourceAttachmentChange" eSuperTypes="#//Diff">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This particular kind of difference describes the fragmentation (or un-fragmentation) of a model element in its own (or back in its parent's) resource."/>
+ </eAnnotations>
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="resourceURI" lowerBound="1"
+ eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="URI of the resource in which the parent mapping's element is now located."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ </eClassifiers>
+ <eClassifiers xsi:type="ecore:EClass" name="ReferenceChange" eSuperTypes="#//Diff">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This particular kind of difference will be used to describe changes within a reference, whether the feature is multi-valued or not. In the case of a MOVE difference, this could actually mean two things : either the value has been moved from one index to another (moving the value at another position of the same reference), or the value has been moved from one container to another. This second case will only happen with containment references."/>
+ </eAnnotations>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="reference" lowerBound="1"
+ eType="ecore:EClass platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EReference">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="The reference in which &quot;something&quot; changed. If this difference is a MOVE from one reference to another, this will point towards the left reference."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="value" eType="ecore:EClass platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EObject">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="References the actual value on which a difference has been detected."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ </eClassifiers>
+ <eClassifiers xsi:type="ecore:EClass" name="AttributeChange" eSuperTypes="#//Diff">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This particular kind of difference will be used to describe changes within an attribute, whether the feature is multi-valued or not."/>
+ </eAnnotations>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="attribute" lowerBound="1"
+ eType="ecore:EClass platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EAttribute">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="The attribute in which &quot;something&quot; changed."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="value" eType="ecore:EDataType platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore#//EJavaObject">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="References the actual value on which a difference has been detected."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ </eClassifiers>
+ <eClassifiers xsi:type="ecore:EClass" name="Conflict">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Instances of this class describe conflicts between one or more differences in the left model as compared to differences in the right model. Conflicts can only happen in the case of three-way comparisons, when we have a common ancestor of both sides."/>
+ </eAnnotations>
+ <eOperations name="getLeftDifferences" lowerBound="1" upperBound="-1" eType="#//Diff">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This can be used to retrieve the list of differences that were made in the left element."/>
+ </eAnnotations>
+ </eOperations>
+ <eOperations name="getRightDifferences" lowerBound="1" upperBound="-1" eType="#//Diff">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This can be used to retrieve the list of differences that were made in the right element."/>
+ </eAnnotations>
+ </eOperations>
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="kind" lowerBound="1" eType="#//ConflictKind">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Describes the kind of this conflict, whether it is a real conflict or a pseudo-conflict."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="differences" lowerBound="2"
+ upperBound="-1" eType="#//Diff" eOpposite="#//Diff/conflict">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This will reference all differences that are related to this conflict. The number of elements contained in this list is &lt;u>at least&lt;/u> two."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ </eClassifiers>
+ <eClassifiers xsi:type="ecore:EClass" name="Equivalence">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Diffs are considered equivalent if merging one is enough to resolve both differences. For example, if a reference has an eOpposite, we will detect one diff for each side of the bidirectional reference, yet merging one of these diffs will automatically update the model in such a way that the second diff is &quot;merged&quot;."/>
+ </eAnnotations>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="differences" lowerBound="2"
+ upperBound="-1" eType="#//Diff" eOpposite="#//Diff/equivalence">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="References the &lt;i>n&lt;/i> diffs composing this equivalence. There are &lt;u>at least&lt;/u> two diffs in this list."/>
+ </eAnnotations>
+ </eStructuralFeatures>
+ </eClassifiers>
+ <eClassifiers xsi:type="ecore:EEnum" name="DifferenceKind">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="The differences detected through EMF Compare can be of 4 general types.&#xD;&#xA;&lt;ul>&#xD;&#xA;&#x9;&lt;li>ADD represent addition of model element or feature values,&lt;/li>&#xD;&#xA;&#x9;&lt;li>DELETE represent suppression of model element or feature values,&lt;/li>&#xD;&#xA;&#x9;&lt;li>CHANGE represent the modification of a feature value,&lt;/li>&#xD;&#xA;&#x9;&lt;li>MOVE will be used for difference on the containment feature of a model element, or differences on the order of a feature's values.&lt;/li>&#xD;&#xA;&lt;/ul>"/>
+ </eAnnotations>
+ <eLiterals name="ADD">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Represents the addition of model elements or feature values."/>
+ </eAnnotations>
+ </eLiterals>
+ <eLiterals name="DELETE" value="1">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Represents the suppression of model elements or feature values."/>
+ </eAnnotations>
+ </eLiterals>
+ <eLiterals name="CHANGE" value="2">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Represents the modification of a feature value."/>
+ </eAnnotations>
+ </eLiterals>
+ <eLiterals name="MOVE" value="3">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Describes a difference on the containment feature of a model element, or differences on the order of a feature's values."/>
+ </eAnnotations>
+ </eLiterals>
+ </eClassifiers>
+ <eClassifiers xsi:type="ecore:EEnum" name="DifferenceSource">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This will be used to represent the source of a detected diff.&#xD;&#xA;&lt;ul>&#xD;&#xA;&#x9;&lt;li>LEFT if the difference has been detected between the left element and its origin,&lt;/li>&#xD;&#xA;&#x9;&lt;li>RIGHT if the difference has been detected between the right element and its origin.&lt;/li>&#xD;&#xA;&lt;/ul>&#xD;&#xA;&lt;b>Note&lt;/b> that differences detected during two-way comparisons will only be LEFT."/>
+ </eAnnotations>
+ <eLiterals name="LEFT">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Will be used if the difference has been detected between the left element and its origin. Differences detected during two-way comparisons will always have this has their source."/>
+ </eAnnotations>
+ </eLiterals>
+ <eLiterals name="RIGHT" value="1">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Will be used if the difference has been detected between the right element and its origin."/>
+ </eAnnotations>
+ </eLiterals>
+ </eClassifiers>
+ <eClassifiers xsi:type="ecore:EEnum" name="DifferenceState">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="This will be used to represent the state of a detected diff.&#xD;&#xA;&lt;ul>&#xD;&#xA;&#x9;&lt;li>UNRESOLVED if the Diff is still in its initial state and the two sides differ,&lt;/li>&#xD;&#xA;&#x9;&lt;li>MERGED if the Diff has already been merged by the user,&lt;/li>&#xD;&#xA;&#x9;&lt;li>DISCARDED if the user chose to ignore this Diff.&lt;/li>&#xD;&#xA;&lt;/ul>"/>
+ </eAnnotations>
+ <eLiterals name="UNRESOLVED" literal="UNRESOLVED">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Indicates that the Diff is still in its initial state."/>
+ </eAnnotations>
+ </eLiterals>
+ <eLiterals name="MERGED" value="1">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Indicates that the Diff has already been merged by the user."/>
+ </eAnnotations>
+ </eLiterals>
+ <eLiterals name="DISCARDED" value="2" literal="DISCARDED">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Indicates that the user chose to ignore this Diff."/>
+ </eAnnotations>
+ </eLiterals>
+ </eClassifiers>
+ <eClassifiers xsi:type="ecore:EEnum" name="ConflictKind">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="Conflicts detected through EMF Compare can be of a number of different types.&#xD;&#xA;&lt;ul>&#xD;&#xA;&#x9;&lt;li>REAL are the conflicts that cannot be merged automatically,&lt;/li>&#xD;&#xA;&#x9;&lt;li>PSEUDO are the &quot;conflicts&quot; that represent the same change made on the two sides, which can thus be automatically merged.&lt;/li>&#xD;&#xA;&lt;/ul>"/>
+ </eAnnotations>
+ <eLiterals name="REAL">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="conflicts that cannot be merged automatically as they represent incompatible differences on the two sides."/>
+ </eAnnotations>
+ </eLiterals>
+ <eLiterals name="PSEUDO" value="1">
+ <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
+ <details key="documentation" value="If the same change has been made on the two sides since the common ancestor, these changes will be marked as &quot;pseudo-conflicting&quot; changes : there are changes, but they can be merged automatically."/>
+ </eAnnotations>
+ </eLiterals>
+ </eClassifiers>
+ <eClassifiers xsi:type="ecore:EDataType" name="EIterable" instanceClassName="java.lang.Iterable">
+ <eTypeParameters name="T"/>
+ </eClassifiers>
+ <eClassifiers xsi:type="ecore:EDataType" name="IEqualityHelper" instanceClassName="org.eclipse.emf.compare.utils.IEqualityHelper"
+ serializable="false"/>
+</ecore:EPackage>
diff --git a/plugins/org.eclipse.emf.compare/model/compare.genmodel b/plugins/org.eclipse.emf.compare/model/compare.genmodel
index b8b596f66..ac14271a0 100644
--- a/plugins/org.eclipse.emf.compare/model/compare.genmodel
+++ b/plugins/org.eclipse.emf.compare/model/compare.genmodel
@@ -1,109 +1,111 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<genmodel:GenModel xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
- xmlns:genmodel="http://www.eclipse.org/emf/2002/GenModel" copyrightText="Copyright (c) 2012 Obeo.&#xD;&#xA;All rights reserved. This program and the accompanying materials&#xD;&#xA;are made available under the terms of the Eclipse Public License v1.0&#xD;&#xA;which accompanies this distribution, and is available at&#xD;&#xA;http://www.eclipse.org/legal/epl-v10.html&#xD;&#xA;&#xD;&#xA;Contributors:&#xD;&#xA; Obeo - initial API and implementation"
- modelDirectory="/org.eclipse.emf.compare/src-gen" editDirectory="/org.eclipse.emf.compare.edit/src-gen"
- editorDirectory="/org.eclipse.emf.compare.editor/src-gen" modelPluginID="org.eclipse.emf.compare"
- modelName="Compare" editPluginClass="org.eclipse.emf.compare.provider.EMFCompareEditPlugin"
- editorPluginClass="org.eclipse.emf.compare.presentation.EMFCompareEditorPlugin"
- nonNLSMarkers="true" rootExtendsClass="org.eclipse.emf.ecore.impl.MinimalEObjectImpl"
- codeFormatting="true" testsDirectory="/org.eclipse.emf.compare.tests/src-gen"
- testSuiteClass="org.eclipse.emf.compare.tests.CompareAllTests" importerID="org.eclipse.emf.importer.ecore"
- complianceLevel="5.0" colorProviders="true" fontProviders="true" runtimeVersion="2.5"
- usedGenPackages="platform:/plugin/org.eclipse.emf.ecore/model/Ecore.genmodel#//ecore">
- <foreignModel>compare.ecore</foreignModel>
- <genPackages prefix="Compare" basePackage="org.eclipse.emf" disposableProviderFactory="true"
- ecorePackage="compare.ecore#/">
- <genEnums typeSafeEnumCompatible="false" ecoreEnum="compare.ecore#//DifferenceKind">
- <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceKind/ADD"/>
- <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceKind/DELETE"/>
- <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceKind/CHANGE"/>
- <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceKind/MOVE"/>
- </genEnums>
- <genEnums typeSafeEnumCompatible="false" ecoreEnum="compare.ecore#//DifferenceSource">
- <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceSource/LEFT"/>
- <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceSource/RIGHT"/>
- </genEnums>
- <genEnums typeSafeEnumCompatible="false" ecoreEnum="compare.ecore#//DifferenceState">
- <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceState/UNRESOLVED"/>
- <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceState/MERGED"/>
- <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceState/DISCARDED"/>
- </genEnums>
- <genEnums typeSafeEnumCompatible="false" ecoreEnum="compare.ecore#//ConflictKind">
- <genEnumLiterals ecoreEnumLiteral="compare.ecore#//ConflictKind/REAL"/>
- <genEnumLiterals ecoreEnumLiteral="compare.ecore#//ConflictKind/PSEUDO"/>
- </genEnums>
- <genDataTypes ecoreDataType="compare.ecore#//EIterable">
- <genTypeParameters ecoreTypeParameter="compare.ecore#//EIterable/T"/>
- </genDataTypes>
- <genDataTypes ecoreDataType="compare.ecore#//IEqualityHelper"/>
- <genClasses ecoreClass="compare.ecore#//Comparison">
- <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference compare.ecore#//Comparison/matchedResources"/>
- <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference compare.ecore#//Comparison/matches"/>
- <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference compare.ecore#//Comparison/conflicts"/>
- <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference compare.ecore#//Comparison/equivalences"/>
- <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//Comparison/threeWay"/>
- <genOperations ecoreOperation="compare.ecore#//Comparison/getDifferences"/>
- <genOperations ecoreOperation="compare.ecore#//Comparison/getDifferences.1">
- <genParameters ecoreParameter="compare.ecore#//Comparison/getDifferences.1/element"/>
- </genOperations>
- <genOperations ecoreOperation="compare.ecore#//Comparison/getMatch">
- <genParameters ecoreParameter="compare.ecore#//Comparison/getMatch/element"/>
- </genOperations>
- <genOperations ecoreOperation="compare.ecore#//Comparison/getEqualityHelper"/>
- </genClasses>
- <genClasses ecoreClass="compare.ecore#//MatchResource">
- <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//MatchResource/leftURI"/>
- <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//MatchResource/rightURI"/>
- <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//MatchResource/originURI"/>
- <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//MatchResource/left"/>
- <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//MatchResource/right"/>
- <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//MatchResource/origin"/>
- <genFeatures property="None" notify="false" createChild="false" ecoreFeature="ecore:EReference compare.ecore#//MatchResource/comparison"/>
- </genClasses>
- <genClasses ecoreClass="compare.ecore#//Match">
- <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference compare.ecore#//Match/submatches"/>
- <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference compare.ecore#//Match/differences"/>
- <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Match/left"/>
- <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Match/right"/>
- <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Match/origin"/>
- <genOperations ecoreOperation="compare.ecore#//Match/getComparison"/>
- <genOperations ecoreOperation="compare.ecore#//Match/getAllSubmatches"/>
- <genOperations ecoreOperation="compare.ecore#//Match/getAllDifferences"/>
- </genClasses>
- <genClasses ecoreClass="compare.ecore#//Diff">
- <genFeatures property="None" notify="false" createChild="false" ecoreFeature="ecore:EReference compare.ecore#//Diff/match"/>
- <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Diff/requires"/>
- <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Diff/requiredBy"/>
- <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Diff/refines"/>
- <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Diff/refinedBy"/>
- <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//Diff/kind"/>
- <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//Diff/source"/>
- <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//Diff/state"/>
- <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Diff/equivalence"/>
- <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Diff/conflict"/>
- <genOperations ecoreOperation="compare.ecore#//Diff/copyRightToLeft"/>
- <genOperations ecoreOperation="compare.ecore#//Diff/copyLeftToRight"/>
- <genOperations ecoreOperation="compare.ecore#//Diff/discard"/>
- </genClasses>
- <genClasses ecoreClass="compare.ecore#//ResourceAttachmentChange">
- <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//ResourceAttachmentChange/resourceURI"/>
- </genClasses>
- <genClasses ecoreClass="compare.ecore#//ReferenceChange">
- <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//ReferenceChange/reference"/>
- <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//ReferenceChange/value"/>
- </genClasses>
- <genClasses ecoreClass="compare.ecore#//AttributeChange">
- <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//AttributeChange/attribute"/>
- <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//AttributeChange/value"/>
- </genClasses>
- <genClasses ecoreClass="compare.ecore#//Conflict">
- <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//Conflict/kind"/>
- <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Conflict/differences"/>
- <genOperations ecoreOperation="compare.ecore#//Conflict/getLeftDifferences"/>
- <genOperations ecoreOperation="compare.ecore#//Conflict/getRightDifferences"/>
- </genClasses>
- <genClasses ecoreClass="compare.ecore#//Equivalence">
- <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Equivalence/differences"/>
- </genClasses>
- </genPackages>
-</genmodel:GenModel>
+<?xml version="1.0" encoding="UTF-8"?>
+<genmodel:GenModel xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
+ xmlns:genmodel="http://www.eclipse.org/emf/2002/GenModel" copyrightText="Copyright (c) 2012 Obeo.&#xD;&#xA;All rights reserved. This program and the accompanying materials&#xD;&#xA;are made available under the terms of the Eclipse Public License v1.0&#xD;&#xA;which accompanies this distribution, and is available at&#xD;&#xA;http://www.eclipse.org/legal/epl-v10.html&#xD;&#xA;&#xD;&#xA;Contributors:&#xD;&#xA; Obeo - initial API and implementation"
+ modelDirectory="/org.eclipse.emf.compare/src-gen" editDirectory="/org.eclipse.emf.compare.edit/src-gen"
+ editorDirectory="/org.eclipse.emf.compare.editor/src-gen" modelPluginID="org.eclipse.emf.compare"
+ modelName="Compare" editPluginClass="org.eclipse.emf.compare.provider.EMFCompareEditPlugin"
+ editorPluginClass="org.eclipse.emf.compare.presentation.EMFCompareEditorPlugin"
+ nonNLSMarkers="true" rootExtendsClass="org.eclipse.emf.ecore.impl.MinimalEObjectImpl"
+ codeFormatting="true" testsDirectory="/org.eclipse.emf.compare.tests/src-gen"
+ testSuiteClass="org.eclipse.emf.compare.tests.CompareAllTests" importerID="org.eclipse.emf.importer.ecore"
+ complianceLevel="5.0" colorProviders="true" fontProviders="true" runtimeVersion="2.5"
+ usedGenPackages="platform:/plugin/org.eclipse.emf.ecore/model/Ecore.genmodel#//ecore">
+ <foreignModel>compare.ecore</foreignModel>
+ <genPackages prefix="Compare" basePackage="org.eclipse.emf" disposableProviderFactory="true"
+ ecorePackage="compare.ecore#/">
+ <genEnums typeSafeEnumCompatible="false" ecoreEnum="compare.ecore#//DifferenceKind">
+ <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceKind/ADD"/>
+ <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceKind/DELETE"/>
+ <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceKind/CHANGE"/>
+ <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceKind/MOVE"/>
+ </genEnums>
+ <genEnums typeSafeEnumCompatible="false" ecoreEnum="compare.ecore#//DifferenceSource">
+ <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceSource/LEFT"/>
+ <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceSource/RIGHT"/>
+ </genEnums>
+ <genEnums typeSafeEnumCompatible="false" ecoreEnum="compare.ecore#//DifferenceState">
+ <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceState/UNRESOLVED"/>
+ <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceState/MERGED"/>
+ <genEnumLiterals ecoreEnumLiteral="compare.ecore#//DifferenceState/DISCARDED"/>
+ </genEnums>
+ <genEnums typeSafeEnumCompatible="false" ecoreEnum="compare.ecore#//ConflictKind">
+ <genEnumLiterals ecoreEnumLiteral="compare.ecore#//ConflictKind/REAL"/>
+ <genEnumLiterals ecoreEnumLiteral="compare.ecore#//ConflictKind/PSEUDO"/>
+ </genEnums>
+ <genDataTypes ecoreDataType="compare.ecore#//EIterable">
+ <genTypeParameters ecoreTypeParameter="compare.ecore#//EIterable/T"/>
+ </genDataTypes>
+ <genDataTypes ecoreDataType="compare.ecore#//IEqualityHelper"/>
+ <genClasses ecoreClass="compare.ecore#//Comparison">
+ <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference compare.ecore#//Comparison/matchedResources"/>
+ <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference compare.ecore#//Comparison/matches"/>
+ <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference compare.ecore#//Comparison/conflicts"/>
+ <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference compare.ecore#//Comparison/equivalences"/>
+ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//Comparison/threeWay"/>
+ <genOperations ecoreOperation="compare.ecore#//Comparison/getDifferences"/>
+ <genOperations ecoreOperation="compare.ecore#//Comparison/getDifferences.1">
+ <genParameters ecoreParameter="compare.ecore#//Comparison/getDifferences.1/element"/>
+ </genOperations>
+ <genOperations ecoreOperation="compare.ecore#//Comparison/getMatch">
+ <genParameters ecoreParameter="compare.ecore#//Comparison/getMatch/element"/>
+ </genOperations>
+ <genOperations ecoreOperation="compare.ecore#//Comparison/getEqualityHelper"/>
+ </genClasses>
+ <genClasses ecoreClass="compare.ecore#//MatchResource">
+ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//MatchResource/leftURI"/>
+ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//MatchResource/rightURI"/>
+ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//MatchResource/originURI"/>
+ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//MatchResource/left"/>
+ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//MatchResource/right"/>
+ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//MatchResource/origin"/>
+ <genFeatures property="None" notify="false" createChild="false" ecoreFeature="ecore:EReference compare.ecore#//MatchResource/comparison"/>
+ </genClasses>
+ <genClasses ecoreClass="compare.ecore#//Match">
+ <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference compare.ecore#//Match/submatches"/>
+ <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference compare.ecore#//Match/differences"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Match/left"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Match/right"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Match/origin"/>
+ <genOperations ecoreOperation="compare.ecore#//Match/getComparison"/>
+ <genOperations ecoreOperation="compare.ecore#//Match/getAllSubmatches"/>
+ <genOperations ecoreOperation="compare.ecore#//Match/getAllDifferences"/>
+ </genClasses>
+ <genClasses ecoreClass="compare.ecore#//Diff">
+ <genFeatures property="None" notify="false" createChild="false" ecoreFeature="ecore:EReference compare.ecore#//Diff/match"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Diff/requires"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Diff/requiredBy"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Diff/implies"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Diff/impliedBy"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Diff/refines"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Diff/refinedBy"/>
+ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//Diff/kind"/>
+ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//Diff/source"/>
+ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//Diff/state"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Diff/equivalence"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Diff/conflict"/>
+ <genOperations ecoreOperation="compare.ecore#//Diff/copyRightToLeft"/>
+ <genOperations ecoreOperation="compare.ecore#//Diff/copyLeftToRight"/>
+ <genOperations ecoreOperation="compare.ecore#//Diff/discard"/>
+ </genClasses>
+ <genClasses ecoreClass="compare.ecore#//ResourceAttachmentChange">
+ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//ResourceAttachmentChange/resourceURI"/>
+ </genClasses>
+ <genClasses ecoreClass="compare.ecore#//ReferenceChange">
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//ReferenceChange/reference"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//ReferenceChange/value"/>
+ </genClasses>
+ <genClasses ecoreClass="compare.ecore#//AttributeChange">
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//AttributeChange/attribute"/>
+ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//AttributeChange/value"/>
+ </genClasses>
+ <genClasses ecoreClass="compare.ecore#//Conflict">
+ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute compare.ecore#//Conflict/kind"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Conflict/differences"/>
+ <genOperations ecoreOperation="compare.ecore#//Conflict/getLeftDifferences"/>
+ <genOperations ecoreOperation="compare.ecore#//Conflict/getRightDifferences"/>
+ </genClasses>
+ <genClasses ecoreClass="compare.ecore#//Equivalence">
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference compare.ecore#//Equivalence/differences"/>
+ </genClasses>
+ </genPackages>
+</genmodel:GenModel>
diff --git a/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/ComparePackage.java b/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/ComparePackage.java
index eb5602bbe..1caaaad38 100644
--- a/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/ComparePackage.java
+++ b/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/ComparePackage.java
@@ -320,13 +320,31 @@ public interface ComparePackage extends EPackage {
int DIFF__REQUIRED_BY = 2;
/**
+ * The feature id for the '<em><b>Implies</b></em>' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ * @ordered
+ */
+ int DIFF__IMPLIES = 3;
+
+ /**
+ * The feature id for the '<em><b>Implied By</b></em>' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ * @ordered
+ */
+ int DIFF__IMPLIED_BY = 4;
+
+ /**
* The feature id for the '<em><b>Refines</b></em>' reference list.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
* @ordered
*/
- int DIFF__REFINES = 3;
+ int DIFF__REFINES = 5;
/**
* The feature id for the '<em><b>Refined By</b></em>' reference list.
@@ -335,7 +353,7 @@ public interface ComparePackage extends EPackage {
* @generated
* @ordered
*/
- int DIFF__REFINED_BY = 4;
+ int DIFF__REFINED_BY = 6;
/**
* The feature id for the '<em><b>Kind</b></em>' attribute.
@@ -344,7 +362,7 @@ public interface ComparePackage extends EPackage {
* @generated
* @ordered
*/
- int DIFF__KIND = 5;
+ int DIFF__KIND = 7;
/**
* The feature id for the '<em><b>Source</b></em>' attribute.
@@ -353,7 +371,7 @@ public interface ComparePackage extends EPackage {
* @generated
* @ordered
*/
- int DIFF__SOURCE = 6;
+ int DIFF__SOURCE = 8;
/**
* The feature id for the '<em><b>State</b></em>' attribute.
@@ -362,7 +380,7 @@ public interface ComparePackage extends EPackage {
* @generated
* @ordered
*/
- int DIFF__STATE = 7;
+ int DIFF__STATE = 9;
/**
* The feature id for the '<em><b>Equivalence</b></em>' reference.
@@ -371,7 +389,7 @@ public interface ComparePackage extends EPackage {
* @generated
* @ordered
*/
- int DIFF__EQUIVALENCE = 8;
+ int DIFF__EQUIVALENCE = 10;
/**
* The feature id for the '<em><b>Conflict</b></em>' reference.
@@ -380,7 +398,7 @@ public interface ComparePackage extends EPackage {
* @generated
* @ordered
*/
- int DIFF__CONFLICT = 9;
+ int DIFF__CONFLICT = 11;
/**
* The number of structural features of the '<em>Diff</em>' class.
@@ -389,7 +407,7 @@ public interface ComparePackage extends EPackage {
* @generated
* @ordered
*/
- int DIFF_FEATURE_COUNT = 10;
+ int DIFF_FEATURE_COUNT = 12;
/**
* The meta object id for the '{@link org.eclipse.emf.compare.impl.ResourceAttachmentChangeImpl <em>Resource Attachment Change</em>}' class.
@@ -429,6 +447,24 @@ public interface ComparePackage extends EPackage {
int RESOURCE_ATTACHMENT_CHANGE__REQUIRED_BY = DIFF__REQUIRED_BY;
/**
+ * The feature id for the '<em><b>Implies</b></em>' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ * @ordered
+ */
+ int RESOURCE_ATTACHMENT_CHANGE__IMPLIES = DIFF__IMPLIES;
+
+ /**
+ * The feature id for the '<em><b>Implied By</b></em>' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ * @ordered
+ */
+ int RESOURCE_ATTACHMENT_CHANGE__IMPLIED_BY = DIFF__IMPLIED_BY;
+
+ /**
* The feature id for the '<em><b>Refines</b></em>' reference list.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
@@ -547,6 +583,24 @@ public interface ComparePackage extends EPackage {
int REFERENCE_CHANGE__REQUIRED_BY = DIFF__REQUIRED_BY;
/**
+ * The feature id for the '<em><b>Implies</b></em>' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ * @ordered
+ */
+ int REFERENCE_CHANGE__IMPLIES = DIFF__IMPLIES;
+
+ /**
+ * The feature id for the '<em><b>Implied By</b></em>' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ * @ordered
+ */
+ int REFERENCE_CHANGE__IMPLIED_BY = DIFF__IMPLIED_BY;
+
+ /**
* The feature id for the '<em><b>Refines</b></em>' reference list.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
@@ -674,6 +728,24 @@ public interface ComparePackage extends EPackage {
int ATTRIBUTE_CHANGE__REQUIRED_BY = DIFF__REQUIRED_BY;
/**
+ * The feature id for the '<em><b>Implies</b></em>' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ * @ordered
+ */
+ int ATTRIBUTE_CHANGE__IMPLIES = DIFF__IMPLIES;
+
+ /**
+ * The feature id for the '<em><b>Implied By</b></em>' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ * @ordered
+ */
+ int ATTRIBUTE_CHANGE__IMPLIED_BY = DIFF__IMPLIED_BY;
+
+ /**
* The feature id for the '<em><b>Refines</b></em>' reference list.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
@@ -1149,6 +1221,28 @@ public interface ComparePackage extends EPackage {
EReference getDiff_RequiredBy();
/**
+ * Returns the meta object for the reference list '{@link org.eclipse.emf.compare.Diff#getImplies <em>Implies</em>}'.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @return the meta object for the reference list '<em>Implies</em>'.
+ * @see org.eclipse.emf.compare.Diff#getImplies()
+ * @see #getDiff()
+ * @generated
+ */
+ EReference getDiff_Implies();
+
+ /**
+ * Returns the meta object for the reference list '{@link org.eclipse.emf.compare.Diff#getImpliedBy <em>Implied By</em>}'.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @return the meta object for the reference list '<em>Implied By</em>'.
+ * @see org.eclipse.emf.compare.Diff#getImpliedBy()
+ * @see #getDiff()
+ * @generated
+ */
+ EReference getDiff_ImpliedBy();
+
+ /**
* Returns the meta object for the reference list '{@link org.eclipse.emf.compare.Diff#getRefines <em>Refines</em>}'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
@@ -1650,6 +1744,22 @@ public interface ComparePackage extends EPackage {
EReference DIFF__REQUIRED_BY = eINSTANCE.getDiff_RequiredBy();
/**
+ * The meta object literal for the '<em><b>Implies</b></em>' reference list feature.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ EReference DIFF__IMPLIES = eINSTANCE.getDiff_Implies();
+
+ /**
+ * The meta object literal for the '<em><b>Implied By</b></em>' reference list feature.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ EReference DIFF__IMPLIED_BY = eINSTANCE.getDiff_ImpliedBy();
+
+ /**
* The meta object literal for the '<em><b>Refines</b></em>' reference list feature.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
diff --git a/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/Diff.java b/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/Diff.java
index 23b9baf5d..8c0bec252 100644
--- a/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/Diff.java
+++ b/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/Diff.java
@@ -29,6 +29,8 @@ import org.eclipse.emf.ecore.EObject;
* <li>{@link org.eclipse.emf.compare.Diff#getMatch <em>Match</em>}</li>
* <li>{@link org.eclipse.emf.compare.Diff#getRequires <em>Requires</em>}</li>
* <li>{@link org.eclipse.emf.compare.Diff#getRequiredBy <em>Required By</em>}</li>
+ * <li>{@link org.eclipse.emf.compare.Diff#getImplies <em>Implies</em>}</li>
+ * <li>{@link org.eclipse.emf.compare.Diff#getImpliedBy <em>Implied By</em>}</li>
* <li>{@link org.eclipse.emf.compare.Diff#getRefines <em>Refines</em>}</li>
* <li>{@link org.eclipse.emf.compare.Diff#getRefinedBy <em>Refined By</em>}</li>
* <li>{@link org.eclipse.emf.compare.Diff#getKind <em>Kind</em>}</li>
@@ -113,6 +115,42 @@ public interface Diff extends EObject {
EList<Diff> getRequiredBy();
/**
+ * Returns the value of the '<em><b>Implies</b></em>' reference list.
+ * The list contents are of type {@link org.eclipse.emf.compare.Diff}.
+ * It is bidirectional and its opposite is '{@link org.eclipse.emf.compare.Diff#getImpliedBy <em>Implied By</em>}'.
+ * <!-- begin-user-doc -->
+ * <p>
+ * If the meaning of the '<em>Implies</em>' reference list isn't clear,
+ * there really should be more of a description here...
+ * </p>
+ * <!-- end-user-doc -->
+ * @return the value of the '<em>Implies</em>' reference list.
+ * @see org.eclipse.emf.compare.ComparePackage#getDiff_Implies()
+ * @see org.eclipse.emf.compare.Diff#getImpliedBy
+ * @model opposite="impliedBy"
+ * @generated
+ */
+ EList<Diff> getImplies();
+
+ /**
+ * Returns the value of the '<em><b>Implied By</b></em>' reference list.
+ * The list contents are of type {@link org.eclipse.emf.compare.Diff}.
+ * It is bidirectional and its opposite is '{@link org.eclipse.emf.compare.Diff#getImplies <em>Implies</em>}'.
+ * <!-- begin-user-doc -->
+ * <p>
+ * If the meaning of the '<em>Implied By</em>' reference list isn't clear,
+ * there really should be more of a description here...
+ * </p>
+ * <!-- end-user-doc -->
+ * @return the value of the '<em>Implied By</em>' reference list.
+ * @see org.eclipse.emf.compare.ComparePackage#getDiff_ImpliedBy()
+ * @see org.eclipse.emf.compare.Diff#getImplies
+ * @model opposite="implies"
+ * @generated
+ */
+ EList<Diff> getImpliedBy();
+
+ /**
* Returns the value of the '<em><b>Refines</b></em>' reference list.
* The list contents are of type {@link org.eclipse.emf.compare.Diff}.
* It is bidirectional and its opposite is '{@link org.eclipse.emf.compare.Diff#getRefinedBy <em>Refined By</em>}'.
@@ -292,9 +330,6 @@ public interface Diff extends EObject {
* <!-- end-model-doc -->
* @model
* @generated
- * @deprecated Use
- * {@link org.eclipse.emf.compare.merge.IMerger#copyRightToLeft(org.eclipse.emf.compare.Diff, org.eclipse.emf.common.util.Monitor)}
- * instead. See javadoc of IMerger.Registry for usage instructions.
*/
@Deprecated
void copyRightToLeft();
@@ -307,9 +342,6 @@ public interface Diff extends EObject {
* <!-- end-model-doc -->
* @model
* @generated
- * @deprecated Use
- * {@link org.eclipse.emf.compare.merge.IMerger#copyLeftToRight(org.eclipse.emf.compare.Diff, org.eclipse.emf.common.util.Monitor)}
- * instead. See javadoc of IMerger.Registry for usage instructions.
*/
@Deprecated
void copyLeftToRight();
diff --git a/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/impl/ComparePackageImpl.java b/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/impl/ComparePackageImpl.java
index e8715ef14..fb11a63c7 100644
--- a/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/impl/ComparePackageImpl.java
+++ b/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/impl/ComparePackageImpl.java
@@ -396,11 +396,29 @@ public class ComparePackageImpl extends EPackageImpl implements ComparePackage {
}
/**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public EReference getDiff_Implies() {
+ return (EReference)diffEClass.getEStructuralFeatures().get(3);
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public EReference getDiff_ImpliedBy() {
+ return (EReference)diffEClass.getEStructuralFeatures().get(4);
+ }
+
+ /**
* <!-- begin-user-doc --> <!-- end-user-doc -->
* @generated
*/
public EReference getDiff_Refines() {
- return (EReference)diffEClass.getEStructuralFeatures().get(3);
+ return (EReference)diffEClass.getEStructuralFeatures().get(5);
}
/**
@@ -408,7 +426,7 @@ public class ComparePackageImpl extends EPackageImpl implements ComparePackage {
* @generated
*/
public EReference getDiff_RefinedBy() {
- return (EReference)diffEClass.getEStructuralFeatures().get(4);
+ return (EReference)diffEClass.getEStructuralFeatures().get(6);
}
/**
@@ -416,7 +434,7 @@ public class ComparePackageImpl extends EPackageImpl implements ComparePackage {
* @generated
*/
public EAttribute getDiff_Kind() {
- return (EAttribute)diffEClass.getEStructuralFeatures().get(5);
+ return (EAttribute)diffEClass.getEStructuralFeatures().get(7);
}
/**
@@ -424,7 +442,7 @@ public class ComparePackageImpl extends EPackageImpl implements ComparePackage {
* @generated
*/
public EAttribute getDiff_Source() {
- return (EAttribute)diffEClass.getEStructuralFeatures().get(6);
+ return (EAttribute)diffEClass.getEStructuralFeatures().get(8);
}
/**
@@ -432,7 +450,7 @@ public class ComparePackageImpl extends EPackageImpl implements ComparePackage {
* @generated
*/
public EAttribute getDiff_State() {
- return (EAttribute)diffEClass.getEStructuralFeatures().get(7);
+ return (EAttribute)diffEClass.getEStructuralFeatures().get(9);
}
/**
@@ -440,7 +458,7 @@ public class ComparePackageImpl extends EPackageImpl implements ComparePackage {
* @generated
*/
public EReference getDiff_Equivalence() {
- return (EReference)diffEClass.getEStructuralFeatures().get(8);
+ return (EReference)diffEClass.getEStructuralFeatures().get(10);
}
/**
@@ -448,7 +466,7 @@ public class ComparePackageImpl extends EPackageImpl implements ComparePackage {
* @generated
*/
public EReference getDiff_Conflict() {
- return (EReference)diffEClass.getEStructuralFeatures().get(9);
+ return (EReference)diffEClass.getEStructuralFeatures().get(11);
}
/**
@@ -656,6 +674,8 @@ public class ComparePackageImpl extends EPackageImpl implements ComparePackage {
createEReference(diffEClass, DIFF__MATCH);
createEReference(diffEClass, DIFF__REQUIRES);
createEReference(diffEClass, DIFF__REQUIRED_BY);
+ createEReference(diffEClass, DIFF__IMPLIES);
+ createEReference(diffEClass, DIFF__IMPLIED_BY);
createEReference(diffEClass, DIFF__REFINES);
createEReference(diffEClass, DIFF__REFINED_BY);
createEAttribute(diffEClass, DIFF__KIND);
@@ -860,6 +880,16 @@ public class ComparePackageImpl extends EPackageImpl implements ComparePackage {
this.getDiff_Requires(),
"requiredBy", null, 0, -1, Diff.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); //$NON-NLS-1$
initEReference(
+ getDiff_Implies(),
+ this.getDiff(),
+ this.getDiff_ImpliedBy(),
+ "implies", null, 0, -1, Diff.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); //$NON-NLS-1$
+ initEReference(
+ getDiff_ImpliedBy(),
+ this.getDiff(),
+ this.getDiff_Implies(),
+ "impliedBy", null, 0, -1, Diff.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); //$NON-NLS-1$
+ initEReference(
getDiff_Refines(),
this.getDiff(),
this.getDiff_RefinedBy(),
diff --git a/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/impl/DiffImpl.java b/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/impl/DiffImpl.java
index 99e636872..57c36625a 100644
--- a/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/impl/DiffImpl.java
+++ b/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/impl/DiffImpl.java
@@ -46,6 +46,8 @@ import org.eclipse.emf.ecore.util.InternalEList;
* <li>{@link org.eclipse.emf.compare.impl.DiffImpl#getMatch <em>Match</em>}</li>
* <li>{@link org.eclipse.emf.compare.impl.DiffImpl#getRequires <em>Requires</em>}</li>
* <li>{@link org.eclipse.emf.compare.impl.DiffImpl#getRequiredBy <em>Required By</em>}</li>
+ * <li>{@link org.eclipse.emf.compare.impl.DiffImpl#getImplies <em>Implies</em>}</li>
+ * <li>{@link org.eclipse.emf.compare.impl.DiffImpl#getImpliedBy <em>Implied By</em>}</li>
* <li>{@link org.eclipse.emf.compare.impl.DiffImpl#getRefines <em>Refines</em>}</li>
* <li>{@link org.eclipse.emf.compare.impl.DiffImpl#getRefinedBy <em>Refined By</em>}</li>
* <li>{@link org.eclipse.emf.compare.impl.DiffImpl#getKind <em>Kind</em>}</li>
@@ -89,6 +91,26 @@ public class DiffImpl extends MinimalEObjectImpl implements Diff {
protected EList<Diff> requiredBy;
/**
+ * The cached value of the '{@link #getImplies() <em>Implies</em>}' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @see #getImplies()
+ * @generated
+ * @ordered
+ */
+ protected EList<Diff> implies;
+
+ /**
+ * The cached value of the '{@link #getImpliedBy() <em>Implied By</em>}' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @see #getImpliedBy()
+ * @generated
+ * @ordered
+ */
+ protected EList<Diff> impliedBy;
+
+ /**
* The cached value of the '{@link #getRefines() <em>Refines</em>}' reference list.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
@@ -283,6 +305,32 @@ public class DiffImpl extends MinimalEObjectImpl implements Diff {
* <!-- end-user-doc -->
* @generated
*/
+ public EList<Diff> getImplies() {
+ if (implies == null) {
+ implies = new EObjectWithInverseResolvingEList.ManyInverse<Diff>(Diff.class, this,
+ ComparePackage.DIFF__IMPLIES, ComparePackage.DIFF__IMPLIED_BY);
+ }
+ return implies;
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public EList<Diff> getImpliedBy() {
+ if (impliedBy == null) {
+ impliedBy = new EObjectWithInverseResolvingEList.ManyInverse<Diff>(Diff.class, this,
+ ComparePackage.DIFF__IMPLIED_BY, ComparePackage.DIFF__IMPLIES);
+ }
+ return impliedBy;
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
public EList<Diff> getRefines() {
if (refines == null) {
refines = new EObjectWithInverseResolvingEList.ManyInverse<Diff>(Diff.class, this,
@@ -556,6 +604,12 @@ public class DiffImpl extends MinimalEObjectImpl implements Diff {
case ComparePackage.DIFF__REQUIRED_BY:
return ((InternalEList<InternalEObject>)(InternalEList<?>)getRequiredBy()).basicAdd(otherEnd,
msgs);
+ case ComparePackage.DIFF__IMPLIES:
+ return ((InternalEList<InternalEObject>)(InternalEList<?>)getImplies()).basicAdd(otherEnd,
+ msgs);
+ case ComparePackage.DIFF__IMPLIED_BY:
+ return ((InternalEList<InternalEObject>)(InternalEList<?>)getImpliedBy()).basicAdd(otherEnd,
+ msgs);
case ComparePackage.DIFF__REFINES:
return ((InternalEList<InternalEObject>)(InternalEList<?>)getRefines()).basicAdd(otherEnd,
msgs);
@@ -590,6 +644,10 @@ public class DiffImpl extends MinimalEObjectImpl implements Diff {
return ((InternalEList<?>)getRequires()).basicRemove(otherEnd, msgs);
case ComparePackage.DIFF__REQUIRED_BY:
return ((InternalEList<?>)getRequiredBy()).basicRemove(otherEnd, msgs);
+ case ComparePackage.DIFF__IMPLIES:
+ return ((InternalEList<?>)getImplies()).basicRemove(otherEnd, msgs);
+ case ComparePackage.DIFF__IMPLIED_BY:
+ return ((InternalEList<?>)getImpliedBy()).basicRemove(otherEnd, msgs);
case ComparePackage.DIFF__REFINES:
return ((InternalEList<?>)getRefines()).basicRemove(otherEnd, msgs);
case ComparePackage.DIFF__REFINED_BY:
@@ -631,6 +689,10 @@ public class DiffImpl extends MinimalEObjectImpl implements Diff {
return getRequires();
case ComparePackage.DIFF__REQUIRED_BY:
return getRequiredBy();
+ case ComparePackage.DIFF__IMPLIES:
+ return getImplies();
+ case ComparePackage.DIFF__IMPLIED_BY:
+ return getImpliedBy();
case ComparePackage.DIFF__REFINES:
return getRefines();
case ComparePackage.DIFF__REFINED_BY:
@@ -673,6 +735,14 @@ public class DiffImpl extends MinimalEObjectImpl implements Diff {
getRequiredBy().clear();
getRequiredBy().addAll((Collection<? extends Diff>)newValue);
return;
+ case ComparePackage.DIFF__IMPLIES:
+ getImplies().clear();
+ getImplies().addAll((Collection<? extends Diff>)newValue);
+ return;
+ case ComparePackage.DIFF__IMPLIED_BY:
+ getImpliedBy().clear();
+ getImpliedBy().addAll((Collection<? extends Diff>)newValue);
+ return;
case ComparePackage.DIFF__REFINES:
getRefines().clear();
getRefines().addAll((Collection<? extends Diff>)newValue);
@@ -717,6 +787,12 @@ public class DiffImpl extends MinimalEObjectImpl implements Diff {
case ComparePackage.DIFF__REQUIRED_BY:
getRequiredBy().clear();
return;
+ case ComparePackage.DIFF__IMPLIES:
+ getImplies().clear();
+ return;
+ case ComparePackage.DIFF__IMPLIED_BY:
+ getImpliedBy().clear();
+ return;
case ComparePackage.DIFF__REFINES:
getRefines().clear();
return;
@@ -756,6 +832,10 @@ public class DiffImpl extends MinimalEObjectImpl implements Diff {
return requires != null && !requires.isEmpty();
case ComparePackage.DIFF__REQUIRED_BY:
return requiredBy != null && !requiredBy.isEmpty();
+ case ComparePackage.DIFF__IMPLIES:
+ return implies != null && !implies.isEmpty();
+ case ComparePackage.DIFF__IMPLIED_BY:
+ return impliedBy != null && !impliedBy.isEmpty();
case ComparePackage.DIFF__REFINES:
return refines != null && !refines.isEmpty();
case ComparePackage.DIFF__REFINED_BY:
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/conflict/DefaultConflictDetector.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/conflict/DefaultConflictDetector.java
index 74f0e745b..a62057d86 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/conflict/DefaultConflictDetector.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/conflict/DefaultConflictDetector.java
@@ -11,6 +11,7 @@
package org.eclipse.emf.compare.conflict;
import static com.google.common.base.Predicates.and;
+import static org.eclipse.emf.compare.internal.utils.ComparisonUtil.isDeleteOrUnsetDiff;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.ofKind;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.onFeature;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.valueIs;
@@ -41,7 +42,6 @@ import org.eclipse.emf.compare.ReferenceChange;
import org.eclipse.emf.compare.ResourceAttachmentChange;
import org.eclipse.emf.compare.internal.SubMatchIterator;
import org.eclipse.emf.compare.utils.ReferenceUtil;
-import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
@@ -156,7 +156,7 @@ public class DefaultConflictDetector implements IConflictDetector {
while (diffIterator.hasNext()) {
Diff extendedCandidate = diffIterator.next();
- if (isDeleteOrUnsetDiff(comparison, extendedCandidate)) {
+ if (isDeleteOrUnsetDiff(extendedCandidate)) {
conflictOn(comparison, diff, extendedCandidate, ConflictKind.PSEUDO);
} else {
conflictOn(comparison, diff, extendedCandidate, ConflictKind.REAL);
@@ -200,8 +200,8 @@ public class DefaultConflictDetector implements IConflictDetector {
// The same value has been changed on both sides in containment references
// This is a conflict, but is it a pseudo-conflict?
ConflictKind kind = ConflictKind.REAL;
- final boolean diffIsDelete = isDeleteOrUnsetDiff(comparison, diff);
- final boolean candidateIsDelete = isDeleteOrUnsetDiff(comparison, candidate);
+ final boolean diffIsDelete = isDeleteOrUnsetDiff(diff);
+ final boolean candidateIsDelete = isDeleteOrUnsetDiff(candidate);
if (diffIsDelete && candidateIsDelete) {
kind = ConflictKind.PSEUDO;
} else if (diff.getMatch() == candidate.getMatch()
@@ -537,7 +537,7 @@ public class DefaultConflictDetector implements IConflictDetector {
if (diff.getKind() == DifferenceKind.DELETE) {
final Predicate<? super Diff> candidateFilter = new ConflictCandidateFilter(diff);
for (Diff extendedCandidate : Iterables.filter(match.getAllDifferences(), candidateFilter)) {
- if (isDeleteOrUnsetDiff(comparison, extendedCandidate)) {
+ if (isDeleteOrUnsetDiff(extendedCandidate)) {
conflictOn(comparison, diff, extendedCandidate, ConflictKind.PSEUDO);
} else {
conflictOn(comparison, diff, extendedCandidate, ConflictKind.REAL);
@@ -606,54 +606,6 @@ public class DefaultConflictDetector implements IConflictDetector {
}
/**
- * This will be called in order to check whether the given diff represents a DELETE or "CHANGE to default"
- * diff. This serves the purpose of determining whether we are in th presence of a real or pseudo
- * conflict.
- *
- * @param comparison
- * The originating comparison of this diff.
- * @param diff
- * Diff we are to check.
- * @return {@code true} if {@code diff} is of "DELETE" kind, or if it is of "CHANGE" kind and the new
- * value of the corresponding feature is the default of that feature.
- */
- private static boolean isDeleteOrUnsetDiff(Comparison comparison, Diff diff) {
- boolean deleteOrUnset = false;
- if (diff.getKind() == DifferenceKind.DELETE) {
- deleteOrUnset = true;
- } else if (diff.getKind() == DifferenceKind.ADD) {
- deleteOrUnset = false;
- } else if (diff instanceof ReferenceChange) {
- final EObject value = ((ReferenceChange)diff).getValue();
- final Match valueMatch = comparison.getMatch(value);
-
- if (valueMatch == null) {
- // out-of-scope value. fall back.
- final Match match = diff.getMatch();
- return diff.getSource() == DifferenceSource.RIGHT && match.getRight() == null
- || diff.getSource() == DifferenceSource.LEFT && match.getLeft() == null;
- } else {
- deleteOrUnset = valueMatch.getOrigin() == value;
- }
- } else if (diff instanceof AttributeChange) {
- final EAttribute attribute = ((AttributeChange)diff).getAttribute();
- final EObject expectedContainer;
- if (diff.getSource() == DifferenceSource.LEFT) {
- expectedContainer = diff.getMatch().getLeft();
- } else {
- expectedContainer = diff.getMatch().getRight();
- }
-
- final Object value = ReferenceUtil.safeEGet(expectedContainer, attribute);
- // Though not the "default value", we consider that an empty string is an unset attribute.
- final Object defaultValue = attribute.getDefaultValue();
- deleteOrUnset = value == null || value.equals(defaultValue)
- || (defaultValue == null && "".equals(value)); //$NON-NLS-1$
- }
- return deleteOrUnset;
- }
-
- /**
* This will be used whenever we check for conflictual MOVEs in order to determine whether we have a
* pseudo conflict or a real conflict.
* <p>
@@ -876,7 +828,7 @@ public class DefaultConflictDetector implements IConflictDetector {
if (conflict == null || !conflict.getDifferences().contains(diff2)) {
if (diff1.getMatch() != diff2.getMatch() && diff2 instanceof ReferenceChange
&& ((ReferenceChange)diff2).getReference().isContainment()) {
- canConflict = !isDeleteOrUnsetDiff(diff2.getMatch().getComparison(), diff2);
+ canConflict = !isDeleteOrUnsetDiff(diff2);
} else {
canConflict = true;
}
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/diff/DefaultDiffEngine.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/diff/DefaultDiffEngine.java
index 117b0244a..ce947507c 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/diff/DefaultDiffEngine.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/diff/DefaultDiffEngine.java
@@ -23,7 +23,7 @@ import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.DifferenceKind;
import org.eclipse.emf.compare.DifferenceSource;
import org.eclipse.emf.compare.Match;
-import org.eclipse.emf.compare.utils.DiffUtil;
+import org.eclipse.emf.compare.internal.utils.DiffUtil;
import org.eclipse.emf.compare.utils.IEqualityHelper;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/ComparisonUtil.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/ComparisonUtil.java
new file mode 100644
index 000000000..7ab62f25d
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/ComparisonUtil.java
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 Obeo.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.internal.utils;
+
+import static com.google.common.collect.Iterables.addAll;
+import static com.google.common.collect.Iterables.concat;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+
+import org.eclipse.emf.compare.AttributeChange;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.DifferenceKind;
+import org.eclipse.emf.compare.DifferenceSource;
+import org.eclipse.emf.compare.Match;
+import org.eclipse.emf.compare.ReferenceChange;
+import org.eclipse.emf.compare.utils.ReferenceUtil;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+/**
+ * This utility class provides common methods for navigation over and querying of the Comparison model.
+ *
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+public final class ComparisonUtil {
+ /** Hides default constructor. */
+ private ComparisonUtil() {
+ // prevents instantiation
+ }
+
+ /**
+ * When merging a {@link Diff}, returns the sub diffs of this given diff, and all associated diffs (see
+ * {@link DiffUtil#getAssociatedDiffs(Iterable, boolean, Diff)}) of these sub diffs.
+ * <p>
+ * If the diff is an {@link org.eclipse.emf.compare.AttributeChange} or a
+ * {@link org.eclipse.emf.compare.ResourceAttachmentChange} , this method will return an empty iterable.
+ * </p>
+ * <p>
+ * If the diff is a {@link ReferenceChange} this method will return all differences contained in the match
+ * that contains the value of the reference change, and all associated diffs of these differences.
+ * </p>
+ *
+ * @param leftToRight
+ * the direction of merge.
+ * @return an iterable containing the sub diffs of this given diff, and all associated diffs of these sub
+ * diffs.
+ * @since 3.0
+ */
+ public static Function<Diff, Iterable<Diff>> getSubDiffs(final boolean leftToRight) {
+ return getSubDiffs(leftToRight, new LinkedHashSet<Diff>());
+ }
+
+ /**
+ * Checks if the given difference is either an addition or a "set" from the default value to a new
+ * reference.
+ *
+ * @param difference
+ * The given difference.
+ * @return <code>true</code> if this is an addition or "set" diff.
+ */
+ public static boolean isAddOrSetDiff(Diff difference) {
+ boolean result = false;
+ if (difference.getKind() == DifferenceKind.ADD) {
+ result = true;
+ } else if (difference.getKind() == DifferenceKind.CHANGE) {
+ final EStructuralFeature feature;
+ if (difference instanceof ReferenceChange) {
+ feature = ((ReferenceChange)difference).getReference();
+ } else if (difference instanceof AttributeChange) {
+ feature = ((AttributeChange)difference).getAttribute();
+ } else {
+ feature = null;
+ }
+
+ if (feature != null && !feature.isMany()) {
+ final Match match = difference.getMatch();
+ final EObject source;
+ if (match.getComparison().isThreeWay()) {
+ source = match.getOrigin();
+ } else {
+ source = match.getRight();
+ }
+
+ if (source == null) {
+ result = true;
+ } else {
+ result = equalToDefault(source, feature);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Checks whether the given feature of the given EObject is set to its default value or the empty String.
+ *
+ * @param object
+ * The object which feature value we need to check.
+ * @param feature
+ * The feature which value we need to check.
+ * @return <code>true</code> is this object's feature is set to a value equal to its default.
+ */
+ private static boolean equalToDefault(EObject object, EStructuralFeature feature) {
+ final Object value = ReferenceUtil.safeEGet(object, feature);
+ final Object defaultValue = feature.getDefaultValue();
+ if (value == null) {
+ return defaultValue == null;
+ }
+ return value.equals(feature.getDefaultValue()) || "".equals(value); //$NON-NLS-1$
+ }
+
+ /**
+ * Checks if the given difference is either a deletion or a "unset" to the default value.
+ *
+ * @param difference
+ * The given difference.
+ * @return <code>true</code> if this is a deletion or "unset" diff.
+ */
+ public static boolean isDeleteOrUnsetDiff(Diff difference) {
+ boolean result = false;
+ if (difference.getKind() == DifferenceKind.DELETE) {
+ result = true;
+ } else if (difference.getKind() == DifferenceKind.CHANGE) {
+ final EStructuralFeature feature;
+ if (difference instanceof ReferenceChange) {
+ feature = ((ReferenceChange)difference).getReference();
+ } else if (difference instanceof AttributeChange) {
+ feature = ((AttributeChange)difference).getAttribute();
+ } else {
+ feature = null;
+ }
+
+ if (feature != null && !feature.isMany()) {
+ final Match match = difference.getMatch();
+ final EObject expectedContainer;
+ if (difference.getSource() == DifferenceSource.LEFT) {
+ expectedContainer = match.getLeft();
+ } else {
+ expectedContainer = match.getRight();
+ }
+
+ if (expectedContainer == null) {
+ result = true;
+ } else {
+ result = equalToDefault(expectedContainer, feature);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * When merging a {@link Diff}, returns the sub diffs of this given diff, and all associated diffs (see
+ * {@link DiffUtil#getAssociatedDiffs(Iterable, boolean, Diff)}) of these sub diffs.
+ * <p>
+ * If the diff is an {@link org.eclipse.emf.compare.AttributeChange} or a
+ * {@link org.eclipse.emf.compare.ResourceAttachmentChange}, this method will return an empty iterable.
+ * </p>
+ * <p>
+ * If the diff is a {@link ReferenceChange} this method will return all differences contained in the match
+ * that contains the value of the reference change, and all associated diffs of these differences.
+ * </p>
+ *
+ * @param leftToRight
+ * the direction of merge.
+ * @param processedDiffs
+ * a set of diffs which have been already processed.
+ * @return an iterable containing the sub diffs of this given diff, and all associated diffs of these sub
+ * diffs.
+ * @since 3.0
+ */
+ private static Function<Diff, Iterable<Diff>> getSubDiffs(final boolean leftToRight,
+ final LinkedHashSet<Diff> processedDiffs) {
+ return new Function<Diff, Iterable<Diff>>() {
+ public Iterable<Diff> apply(Diff diff) {
+ if (diff instanceof ReferenceChange) {
+ Match matchOfValue = diff.getMatch().getComparison().getMatch(
+ ((ReferenceChange)diff).getValue());
+ if (((ReferenceChange)diff).getReference().isContainment()) {
+ final Iterable<Diff> subDiffs = matchOfValue.getAllDifferences();
+ addAll(processedDiffs, subDiffs);
+ final Iterable<Diff> associatedDiffs = getAssociatedDiffs(diff, subDiffs,
+ processedDiffs, leftToRight);
+ return ImmutableSet.copyOf(concat(subDiffs, associatedDiffs));
+ }
+ }
+ return ImmutableSet.of();
+ }
+ };
+ }
+
+ /**
+ * When merging a {@link Diff}, returns the associated diffs of the sub diffs of the diff, and all sub
+ * diffs (see {@link DiffUtil#getSubDiffs(boolean)}) of these associated diffs.
+ * <p>
+ * The associated diffs of a diff are :
+ * <p>
+ * - {@link Diff#getRequiredBy()} if the source of the diff is the left side and the direction of the
+ * merge is right to left.
+ * </p>
+ * <p>
+ * - {@link Diff#getRequiredBy()} if the source of the diff is the right side and the direction of the
+ * merge is left to right.
+ * </p>
+ * <p>
+ * - {@link Diff#getRequires()} if the source of the diff is the left side and the direction of the merge
+ * is left to right.
+ * </p>
+ * <p>
+ * - {@link Diff#getRequires()} if the source of the diff is the right side and the direction of the merge
+ * is right to left.
+ * </p>
+ * </p>
+ *
+ * @param diffRoot
+ * the given diff.
+ * @param subDiffs
+ * the iterable of sub diffs for which we want the associated diffs.
+ * @param processedDiffs
+ * a set of diffs which have been already processed.
+ * @param leftToRight
+ * the direction of merge.
+ * @return an iterable containing the associated diffs of these given sub diffs, and all sub diffs of
+ * these associated diffs.
+ * @since 3.0
+ */
+ private static Iterable<Diff> getAssociatedDiffs(final Diff diffRoot, Iterable<Diff> subDiffs,
+ LinkedHashSet<Diff> processedDiffs, boolean leftToRight) {
+ Collection<Diff> associatedDiffs = new HashSet<Diff>();
+ for (Diff diff : subDiffs) {
+ final Collection<Diff> reqs = new LinkedHashSet<Diff>();
+ if (leftToRight) {
+ if (diff.getSource() == DifferenceSource.LEFT) {
+ reqs.addAll(diff.getRequires());
+ } else {
+ reqs.addAll(diff.getRequiredBy());
+ }
+ } else {
+ if (diff.getSource() == DifferenceSource.LEFT) {
+ reqs.addAll(diff.getRequiredBy());
+ } else {
+ reqs.addAll(diff.getRequires());
+ }
+ }
+ reqs.remove(diffRoot);
+ associatedDiffs.addAll(reqs);
+ for (Diff req : reqs) {
+ if (!Iterables.contains(subDiffs, req) && !processedDiffs.contains(req)) {
+ processedDiffs.add(req);
+ addAll(associatedDiffs, getSubDiffs(leftToRight, processedDiffs).apply(req));
+ }
+ }
+ }
+ return associatedDiffs;
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/DiffUtil.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/DiffUtil.java
new file mode 100644
index 000000000..dfa567f9a
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/DiffUtil.java
@@ -0,0 +1,1057 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 Obeo.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.internal.utils;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Multiset;
+import com.google.common.collect.Sets;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
+
+import org.eclipse.emf.compare.AttributeChange;
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.DifferenceKind;
+import org.eclipse.emf.compare.DifferenceSource;
+import org.eclipse.emf.compare.DifferenceState;
+import org.eclipse.emf.compare.EMFCompareMessages;
+import org.eclipse.emf.compare.Match;
+import org.eclipse.emf.compare.ReferenceChange;
+import org.eclipse.emf.compare.utils.IEqualityHelper;
+import org.eclipse.emf.compare.utils.ReferenceUtil;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.ecore.util.InternalEList;
+
+/**
+ * This utility class will be used to provide similarity implementations.
+ *
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+public final class DiffUtil {
+ /** This utility class does not need to be instantiated. */
+ private DiffUtil() {
+ // Hides default constructor
+ }
+
+ /**
+ * Computes the dice coefficient between the two given String's bigrams.
+ * <p>
+ * This implementation is case sensitive.
+ * </p>
+ *
+ * @param first
+ * First of the two Strings to compare.
+ * @param second
+ * Second of the two Strings to compare.
+ * @return The dice coefficient of the two given String's bigrams, ranging from 0 to 1.
+ */
+ public static double diceCoefficient(String first, String second) {
+ final char[] str1 = first.toCharArray();
+ final char[] str2 = second.toCharArray();
+
+ final double coefficient;
+
+ if (Arrays.equals(str1, str2)) {
+ coefficient = 1d;
+ } else if (str1.length <= 2 || str2.length <= 2) {
+ int equalChars = 0;
+
+ for (int i = 0; i < Math.min(str1.length, str2.length); i++) {
+ if (str1[i] == str2[i]) {
+ equalChars++;
+ }
+ }
+
+ int union = str1.length + str2.length;
+ if (str1.length != str2.length) {
+ coefficient = (double)equalChars / union;
+ } else {
+ coefficient = ((double)equalChars * 2) / union;
+ }
+ } else {
+ Set<String> s1Bigrams = Sets.newHashSet();
+ Set<String> s2Bigrams = Sets.newHashSet();
+
+ for (int i = 0; i < str1.length - 1; i++) {
+ char[] chars = new char[] {str1[i], str1[i + 1], };
+ s1Bigrams.add(String.valueOf(chars));
+ }
+ for (int i = 0; i < str2.length - 1; i++) {
+ char[] chars = new char[] {str2[i], str2[i + 1], };
+ s2Bigrams.add(String.valueOf(chars));
+ }
+
+ Set<String> intersection = Sets.intersection(s1Bigrams, s2Bigrams);
+ coefficient = (2d * intersection.size()) / (s1Bigrams.size() + s2Bigrams.size());
+ }
+
+ return coefficient;
+ }
+
+ /**
+ * This will compute the longest common subsequence between the two given Lists, ignoring any object that
+ * is included in {@code ignoredElements}. We will use
+ * {@link IEqualityHelper#matchingValues(Object, Object)} in order to try and match the values from both
+ * lists two-by-two. This can thus be used both for reference values or attribute values. If there are two
+ * subsequences of the same "longest" length, the first (according to the second argument) will be
+ * returned.
+ * <p>
+ * Take note that this might be slower than {@link #longestCommonSubsequence(Comparison, List, List)} and
+ * should only be used when elements should be removed from the potential LCS. This is mainly aimed at
+ * merge operations during three-way comparisons as some objects might be in conflict and thus shifting
+ * the computed insertion indices.
+ * </p>
+ * <p>
+ * Please see {@link #longestCommonSubsequence(Comparison, List, List)} for a more complete description.
+ * </p>
+ *
+ * @param comparison
+ * This will be used in order to retrieve the Match for EObjects when comparing them.
+ * @param ignoredElements
+ * Specifies elements that should be excluded from the subsequences.
+ * @param sequence1
+ * First of the two sequences to consider.
+ * @param sequence2
+ * Second of the two sequences to consider.
+ * @param <E>
+ * Type of the sequences content.
+ * @return The LCS of the two given sequences. Will never be the same instance as one of the input
+ * sequences.
+ * @see #longestCommonSubsequence(Comparison, List, List).
+ */
+ public static <E> List<E> longestCommonSubsequence(Comparison comparison, Iterable<E> ignoredElements,
+ List<E> sequence1, List<E> sequence2) {
+ final List<E> copy1 = Lists.newArrayList(sequence1);
+ final List<E> copy2 = Lists.newArrayList(sequence2);
+
+ // Reduce sets
+ final List<E> prefix = trimPrefix(comparison, ignoredElements, copy1, copy2);
+ final List<E> suffix = trimSuffix(comparison, ignoredElements, copy1, copy2);
+
+ final List<E> subLCS;
+ // FIXME extract an interface for the LCS and properly separate these two differently typed
+ // implementations.
+ if (copy1.size() > Short.MAX_VALUE || copy2.size() > Short.MAX_VALUE) {
+ subLCS = intLongestCommonSubsequence(comparison, ignoredElements, copy1, copy2);
+ } else {
+ subLCS = shortLongestCommonSubsequence(comparison, ignoredElements, copy1, copy2);
+ }
+
+ return ImmutableList.copyOf(Iterables.concat(prefix, subLCS, suffix));
+ }
+
+ /**
+ * This will compute the longest common subsequence between the two given Lists. We will use
+ * {@link IEqualityHelper#matchingValues(Object, Object)} in order to try and match the values from both
+ * lists two-by-two. This can thus be used both for reference values or attribute values. If there are two
+ * subsequences of the same "longest" length, the first (according to the second argument) will be
+ * returned.
+ * <p>
+ * For example, it the two given sequence are, in this order, <code>{"a", "b", "c", "d", "e"}</code> and
+ * <code>{"c", "z", "d", "a", "b"}</code>, there are two "longest" subsequences : <code>{"a", "b"}</code>
+ * and <code>{"c", "d"}</code>. The first of those two subsequences in the second list is
+ * <code>{"c", "d"}</code>. On the other hand, the LCS of <code>{"a", "b", "c", "d", "e"}</code> and
+ * <code>{"y", "c", "d", "e", "b"}</code> is <code>{"c", "d", "e"}</code>.
+ * </p>
+ * <p>
+ * The following algorithm has been inferred from the wikipedia article on the Longest Common Subsequence,
+ * http://en.wikipedia.org/wiki/Longest_common_subsequence_problem at the time of writing. It is
+ * decomposed in two : we first compute the LCS matrix, then we backtrack through the input to determine
+ * the LCS. Evaluation will be shortcut after the first part if the LCS is one of the two input sequences.
+ * </p>
+ * <p>
+ * Note : we are not using Iterables as input in order to make use of the random access cost of
+ * ArrayLists. This might also be converted to directly use arrays. This implementation will not play well
+ * with LinkedLists or any List which needs to iterate over the values for each call to
+ * {@link List#get(int)}, i.e any list which is not instanceof RandomAccess or does not satisfy its
+ * contract.
+ * </p>
+ *
+ * @param comparison
+ * This will be used in order to retrieve the Match for EObjects when comparing them.
+ * @param sequence1
+ * First of the two sequences to consider.
+ * @param sequence2
+ * Second of the two sequences to consider.
+ * @param <E>
+ * Type of the sequences content.
+ * @return The LCS of the two given sequences. Will never be the same instance as one of the input
+ * sequences.
+ */
+ public static <E> List<E> longestCommonSubsequence(Comparison comparison, List<E> sequence1,
+ List<E> sequence2) {
+ return longestCommonSubsequence(comparison, Collections.<E> emptyList(), sequence1, sequence2);
+ }
+
+ /**
+ * Trims and returns the common prefix of the two given sequences. All ignored elements within or after
+ * this common prefix will also be trimmed.
+ * <p>
+ * Note that the two given sequences will be modified in-place.
+ * </p>
+ *
+ * @param comparison
+ * This will be used in order to retrieve the Match for EObjects when comparing them.
+ * @param ignoredElements
+ * Specifies elements that should be excluded from the subsequences.
+ * @param sequence1
+ * First of the two sequences to consider.
+ * @param sequence2
+ * Second of the two sequences to consider.
+ * @param <E>
+ * Type of the sequences content.
+ * @return The common prefix of the two given sequences, less their ignored elements. As a side note, both
+ * {@code sequence1} and {@code sequence2} will have been trimmed of their prefix when this
+ * returns.
+ */
+ private static <E> List<E> trimPrefix(Comparison comparison, Iterable<E> ignoredElements,
+ List<E> sequence1, List<E> sequence2) {
+ final IEqualityHelper equalityHelper = comparison.getEqualityHelper();
+ final int size1 = sequence1.size();
+ final int size2 = sequence2.size();
+
+ final List<E> prefix = Lists.newArrayList();
+ int start1 = 1;
+ int start2 = 1;
+ boolean matching = true;
+ while (start1 <= size1 && start2 <= size2 && matching) {
+ final E first = sequence1.get(start1 - 1);
+ final E second = sequence2.get(start2 - 1);
+ if (equalityHelper.matchingValues(first, second)) {
+ prefix.add(first);
+ start1++;
+ start2++;
+ } else {
+ boolean ignore1 = contains(comparison, equalityHelper, ignoredElements, first);
+ boolean ignore2 = contains(comparison, equalityHelper, ignoredElements, second);
+ if (ignore1) {
+ start1++;
+ }
+ if (ignore2) {
+ start2++;
+ }
+ if (!ignore1 && !ignore2) {
+ matching = false;
+ }
+ }
+ }
+ sequence1.subList(0, start1 - 1).clear();
+ sequence2.subList(0, start2 - 1).clear();
+
+ return prefix;
+ }
+
+ /**
+ * Trims and returns the common suffix of the two given sequences. All ignored elements within or before
+ * this common suffix will also be trimmed.
+ * <p>
+ * Note that the two given sequences will be modified in-place.
+ * </p>
+ *
+ * @param comparison
+ * This will be used in order to retrieve the Match for EObjects when comparing them.
+ * @param ignoredElements
+ * Specifies elements that should be excluded from the subsequences.
+ * @param sequence1
+ * First of the two sequences to consider.
+ * @param sequence2
+ * Second of the two sequences to consider.
+ * @param <E>
+ * Type of the sequences content.
+ * @return The common suffix of the two given sequences, less their ignored elements. As a side note, both
+ * {@code sequence1} and {@code sequence2} will have been trimmed of their suffix when this
+ * returns.
+ */
+ private static <E> List<E> trimSuffix(Comparison comparison, Iterable<E> ignoredElements,
+ List<E> sequence1, List<E> sequence2) {
+ final IEqualityHelper equalityHelper = comparison.getEqualityHelper();
+ final int size1 = sequence1.size();
+ final int size2 = sequence2.size();
+
+ final List<E> suffix = Lists.newArrayList();
+ int end1 = size1;
+ int end2 = size2;
+ boolean matching = true;
+ while (end1 > 0 && end2 > 0 && matching) {
+ final E first = sequence1.get(end1 - 1);
+ final E second = sequence2.get(end2 - 1);
+ if (equalityHelper.matchingValues(first, second)) {
+ suffix.add(first);
+ end1--;
+ end2--;
+ } else {
+ boolean ignore1 = contains(comparison, equalityHelper, ignoredElements, first);
+ boolean ignore2 = contains(comparison, equalityHelper, ignoredElements, second);
+ if (ignore1) {
+ end1--;
+ }
+ if (ignore2) {
+ end2--;
+ }
+ if (!ignore1 && !ignore2) {
+ matching = false;
+ }
+ }
+ }
+ sequence1.subList(end1, size1).clear();
+ sequence2.subList(end2, size2).clear();
+
+ return Lists.reverse(suffix);
+ }
+
+ /**
+ * Checks whether the given {@code sequence} contains the given {@code element} according to the semantics
+ * of the given {@code equalityHelper}.
+ *
+ * @param comparison
+ * This will be used in order to retrieve the Match for EObjects when comparing them.
+ * @param equalityHelper
+ * The {@link IEqualityHelper} gives us the necessary semantics for Object matching.
+ * @param sequence
+ * The sequence which elements we need to compare with {@code element}.
+ * @param element
+ * The element we are seeking in {@code sequence}.
+ * @param <E>
+ * Type of the sequence content.
+ * @return {@code true} if the given {@code sequence} contains an element matching {@code element},
+ * {@code false} otherwise.
+ * @see IEqualityHelper#matchingValues(Comparison, Object, Object)
+ */
+ private static <E> boolean contains(Comparison comparison, IEqualityHelper equalityHelper,
+ Iterable<E> sequence, E element) {
+ final Iterator<E> iterator = sequence.iterator();
+ while (iterator.hasNext()) {
+ E candidate = iterator.next();
+ if (equalityHelper.matchingValues(candidate, element)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * This is a classic, single-threaded implementation. We use shorts for the score matrix so as to limit
+ * the memory cost (we know the max LCS length is not greater than Short#MAX_VALUE).
+ *
+ * @param comparison
+ * This will be used in order to retrieve the Match for EObjects when comparing them.
+ * @param ignoredElements
+ * Specifies elements that should be excluded from the subsequences.
+ * @param sequence1
+ * First of the two sequences to consider.
+ * @param sequence2
+ * Second of the two sequences to consider.
+ * @param <E>
+ * Type of the sequences content.
+ * @return The LCS of the two given sequences. Will never be the same instance as one of the input
+ * sequences.
+ */
+ private static <E> List<E> shortLongestCommonSubsequence(Comparison comparison,
+ Iterable<E> ignoredElements, List<E> sequence1, List<E> sequence2) {
+ final IEqualityHelper equalityHelper = comparison.getEqualityHelper();
+ final int size1 = sequence1.size();
+ final int size2 = sequence2.size();
+
+ final short[][] matrix = new short[size1 + 1][size2 + 1];
+
+ // Compute the LCS matrix
+ for (int i = 1; i <= size1; i++) {
+ final E first = sequence1.get(i - 1);
+ for (int j = 1; j <= size2; j++) {
+ // assume array dereferencing and arithmetics faster than equals
+ final short current = matrix[i - 1][j - 1];
+ final short nextIfNoMatch = (short)Math.max(matrix[i - 1][j], matrix[i][j - 1]);
+
+ if (nextIfNoMatch > current) {
+ matrix[i][j] = nextIfNoMatch;
+ } else {
+ final E second = sequence2.get(j - 1);
+ if (equalityHelper.matchingValues(first, second)
+ && !contains(comparison, equalityHelper, ignoredElements, second)) {
+ matrix[i][j] = (short)(1 + current);
+ } else {
+ matrix[i][j] = nextIfNoMatch;
+ }
+ }
+ }
+ }
+
+ // Traceback the matrix to create the final LCS
+ int current1 = size1;
+ int current2 = size2;
+ final List<E> result = Lists.newArrayList();
+
+ while (current1 > 0 && current2 > 0) {
+ final short currentLength = matrix[current1][current2];
+ final short nextLeft = matrix[current1][current2 - 1];
+ final short nextUp = matrix[current1 - 1][current2];
+ if (currentLength > nextLeft && currentLength > nextUp) {
+ result.add(sequence1.get(current1 - 1));
+ current1--;
+ current2--;
+ } else if (nextLeft >= nextUp) {
+ current2--;
+ } else {
+ current1--;
+ }
+ }
+
+ return Lists.reverse(result);
+ }
+
+ /**
+ * This is a classic, single-threaded implementation. We know the max LCS length is greater than
+ * Short#MAX_VALUE... the score matrix will thus be int-typed, resulting in a huge memory cost.
+ *
+ * @param comparison
+ * This will be used in order to retrieve the Match for EObjects when comparing them.
+ * @param ignoredElements
+ * Specifies elements that should be excluded from the subsequences.
+ * @param sequence1
+ * First of the two sequences to consider.
+ * @param sequence2
+ * Second of the two sequences to consider.
+ * @param <E>
+ * Type of the sequences content.
+ * @return The LCS of the two given sequences. Will never be the same instance as one of the input
+ * sequences.
+ */
+ private static <E> List<E> intLongestCommonSubsequence(Comparison comparison,
+ Iterable<E> ignoredElements, List<E> sequence1, List<E> sequence2) {
+ final IEqualityHelper equalityHelper = comparison.getEqualityHelper();
+ final int size1 = sequence1.size();
+ final int size2 = sequence2.size();
+
+ final int[][] matrix = new int[size1 + 1][size2 + 1];
+
+ // Compute the LCS matrix
+ for (int i = 1; i <= size1; i++) {
+ final E first = sequence1.get(i - 1);
+ for (int j = 1; j <= size2; j++) {
+ // assume array dereferencing and arithmetics faster than equals
+ final int current = matrix[i - 1][j - 1];
+ final int nextIfNoMatch = Math.max(matrix[i - 1][j], matrix[i][j - 1]);
+
+ if (nextIfNoMatch > current) {
+ matrix[i][j] = nextIfNoMatch;
+ } else {
+ final E second = sequence2.get(j - 1);
+ if (equalityHelper.matchingValues(first, second)
+ && !contains(comparison, equalityHelper, ignoredElements, second)) {
+ matrix[i][j] = 1 + current;
+ } else {
+ matrix[i][j] = nextIfNoMatch;
+ }
+ }
+ }
+ }
+
+ // Traceback the matrix to create the final LCS
+ int current1 = size1;
+ int current2 = size2;
+ final List<E> result = Lists.newArrayList();
+
+ while (current1 > 0 && current2 > 0) {
+ final int currentLength = matrix[current1][current2];
+ final int nextLeft = matrix[current1][current2 - 1];
+ final int nextUp = matrix[current1 - 1][current2];
+ if (currentLength > nextLeft && currentLength > nextUp) {
+ result.add(sequence1.get(current1 - 1));
+ current1--;
+ current2--;
+ } else if (nextLeft >= nextUp) {
+ current2--;
+ } else {
+ current1--;
+ }
+ }
+
+ return Lists.reverse(result);
+ }
+
+ /*
+ * TODO perf : all "lookups" in source and target could be rewritten by using the lcs elements' matches.
+ * This may or may not help, should be profiled.
+ */
+ /**
+ * This will try and determine the index at which a given element from the {@code source} list should be
+ * inserted in the {@code target} list. We expect {@code newElement} to be an element from the
+ * {@code source} or to have a Match that allows us to map it to one of the {@code source} list's
+ * elements.
+ * <p>
+ * The expected insertion index will always be relative to the Longest Common Subsequence (LCS) between
+ * the two given lists, ignoring all elements from that LCS that have changed between the target list and
+ * the common origin of the two. If there are more than one "longest" subsequence between the two lists,
+ * the insertion index will be relative to the first that comes in the {@code target} list.
+ * </p>
+ * <p>
+ * Note : we are not using Iterables as input in order to make use of the random access cost of
+ * ArrayLists. This might also be converted to directly use arrays. This implementation will not play well
+ * with LinkedLists or any List which needs to iterate over the values for each call to
+ * {@link List#get(int)}, i.e any list which is not instanceof RandomAccess or does not satisfy its
+ * contract.
+ * </p>
+ *
+ * @param comparison
+ * This will be used in order to retrieve the Match for EObjects when comparing them.
+ * @param ignoredElements
+ * If there are elements from {@code target} that should be ignored when searching for an
+ * insertion index, set them here. Can be {@code null} or an empty list.
+ * @param source
+ * The List from which one element has to be added to the {@code target} list.
+ * @param target
+ * The List into which one element from {@code source} has to be added.
+ * @param newElement
+ * The element from {@code source} that needs to be added into {@code target}.
+ * @param <E>
+ * Type of the sequences content.
+ * @return The index at which {@code newElement} should be inserted in {@code target}.
+ * @see #longestCommonSubsequence(Comparison, List, List)
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ public static <E> int findInsertionIndex(Comparison comparison, Iterable<E> ignoredElements,
+ List<E> source, List<E> target, E newElement) {
+ final IEqualityHelper equalityHelper = comparison.getEqualityHelper();
+
+ // We assume that "newElement" is in source but not in the target yet
+ final List<E> lcs;
+ if (ignoredElements != null) {
+ lcs = longestCommonSubsequence(comparison, ignoredElements, source, target);
+ } else {
+ lcs = longestCommonSubsequence(comparison, source, target);
+ }
+
+ E firstLCS = null;
+ E lastLCS = null;
+ if (lcs.size() > 0) {
+ firstLCS = lcs.get(0);
+ lastLCS = lcs.listIterator(lcs.size()).previous();
+ }
+
+ final int noLCS = -2;
+ int currentIndex = -1;
+ int firstLCSIndex = -1;
+ int lastLCSIndex = -1;
+ if (firstLCS == null) {
+ // We have no LCS
+ firstLCSIndex = noLCS;
+ lastLCSIndex = noLCS;
+ }
+
+ ListIterator<E> sourceIterator = source.listIterator();
+ for (int i = 0; sourceIterator.hasNext() && (currentIndex == -1 || firstLCSIndex == -1); i++) {
+ final E sourceElement = sourceIterator.next();
+ if (currentIndex == -1 && equalityHelper.matchingValues(sourceElement, newElement)) {
+ currentIndex = i;
+ }
+ if (firstLCSIndex == -1 && equalityHelper.matchingValues(sourceElement, firstLCS)) {
+ firstLCSIndex = i;
+ }
+ }
+ // The list may contain duplicates, use a reverse iteration to find the last from LCS.
+ final int sourceSize = source.size();
+ sourceIterator = source.listIterator(sourceSize);
+ for (int i = sourceSize - 1; sourceIterator.hasPrevious() && lastLCSIndex == -1; i--) {
+ final E sourceElement = sourceIterator.previous();
+ if (lastLCSIndex == -1 && equalityHelper.matchingValues(sourceElement, lastLCS)) {
+ lastLCSIndex = i;
+ }
+ }
+
+ int insertionIndex = -1;
+ if (firstLCSIndex == noLCS) {
+ // We have no LCS. The two lists have no element in common. Insert at the very end of the target.
+ insertionIndex = target.size();
+ } else if (currentIndex < firstLCSIndex) {
+ // The object we are to insert is before the LCS in source.
+ insertionIndex = insertBeforeLCS(target, equalityHelper, firstLCS);
+ } else if (currentIndex > lastLCSIndex) {
+ // The object we are to insert is after the LCS in source.
+ insertionIndex = findInsertionIndexAfterLCS(target, equalityHelper, lastLCS);
+ } else {
+ // Our object is in-between two elements A and B of the LCS in source
+ insertionIndex = findInsertionIndexWithinLCS(source, target, equalityHelper, lcs, currentIndex);
+ }
+
+ // We somehow failed to determine the insertion index. Insert at the very end.
+ if (insertionIndex == -1) {
+ insertionIndex = target.size();
+ }
+
+ return insertionIndex;
+ }
+
+ /**
+ * This will be called to try and find the insertion index for an element that is located in-between two
+ * elements of the LCS between {@code source} and {@code target}.
+ *
+ * @param source
+ * The List from which one element has to be added to the {@code target} list.
+ * @param target
+ * The List into which one element from {@code source} has to be added.
+ * @param equalityHelper
+ * The equality helper to use for this computation.
+ * @param lcs
+ * The lcs between {@code source} and {@code target}.
+ * @param currentIndex
+ * Current index (in {@code source} of the element we are to insert into {@code target}.
+ * @param <E>
+ * Type of the sequences content.
+ * @return The index in the target list in which should be inserted that element.
+ */
+ private static <E> int findInsertionIndexWithinLCS(List<E> source, List<E> target,
+ final IEqualityHelper equalityHelper, final List<E> lcs, int currentIndex) {
+ int insertionIndex = -1;
+ /*
+ * If any element of the subsequence {<index of A>, <index of B>} from source had been in the same
+ * subsequence in target, it would have been part of the LCS. We thus know none is.
+ */
+ // The insertion index will be just after A in target
+
+ // First, find which element of the LCS is "A"
+ int lcsIndexOfSubsequenceStart = -1;
+ for (int i = 0; i < currentIndex; i++) {
+ final E sourceElement = source.get(i);
+
+ boolean isInLCS = false;
+ for (int j = lcsIndexOfSubsequenceStart + 1; j < lcs.size() && !isInLCS; j++) {
+ final E lcsElement = lcs.get(j);
+
+ if (equalityHelper.matchingValues(sourceElement, lcsElement)) {
+ isInLCS = true;
+ lcsIndexOfSubsequenceStart++;
+ }
+ }
+ }
+
+ // Do we have duplicates before A in the lcs?
+ final Multiset<E> dupesLCS = HashMultiset.create(lcs.subList(0, lcsIndexOfSubsequenceStart + 1));
+ final E subsequenceStart = lcs.get(lcsIndexOfSubsequenceStart);
+ int duplicatesToGo = dupesLCS.count(subsequenceStart) - 1;
+
+ // Then, find the index of "A" in target
+ for (int i = 0; i < target.size() && insertionIndex == -1; i++) {
+ final E targetElement = target.get(i);
+
+ if (equalityHelper.matchingValues(targetElement, subsequenceStart)) {
+ if (duplicatesToGo > 0) {
+ duplicatesToGo--;
+ } else {
+ insertionIndex = i + 1;
+ }
+ }
+ }
+
+ return insertionIndex;
+ }
+
+ /**
+ * This will be called when we are to insert an element after the LCS in the {@code target} list.
+ *
+ * @param target
+ * The List into which one element has to be added.
+ * @param equalityHelper
+ * The equality helper to use for this computation.
+ * @param lastLCS
+ * The last element of the LCS.
+ * @param <E>
+ * Type of the sequences content.
+ * @return The index to use for insertion into {@code target} in order to add an element just after the
+ * LCS.
+ */
+ private static <E> int findInsertionIndexAfterLCS(List<E> target, IEqualityHelper equalityHelper,
+ E lastLCS) {
+ int insertionIndex = -1;
+ // The insertion index will be inside the subsequence {<LCS end>, <list.size()>} in target.
+ /*
+ * We'll insert it just after the LCS end : there cannot be any common element between the two lists
+ * "after" the LCS since it would be part of the LCS itself.
+ */
+ for (int i = target.size() - 1; i >= 0 && insertionIndex == -1; i--) {
+ final E targetElement = target.get(i);
+ if (equalityHelper.matchingValues(targetElement, lastLCS)) {
+ // We've reached the last element of the LCS in target. insert after it.
+ insertionIndex = i + 1;
+ }
+ }
+ return insertionIndex;
+ }
+
+ /**
+ * This will be called when we are to insert an element before the LCS in the {@code target} list.
+ *
+ * @param target
+ * The List into which one element has to be added.
+ * @param equalityHelper
+ * The equality helper to use for this computation.
+ * @param firstLCS
+ * The first element of the LCS.
+ * @param <E>
+ * Type of the sequences content.
+ * @return The index to use for insertion into {@code target} in order to add an element just before the
+ * LCS.
+ */
+ private static <E> int insertBeforeLCS(List<E> target, IEqualityHelper equalityHelper, E firstLCS) {
+ int insertionIndex = -1;
+ // The insertion index will be inside the subsequence {0, <LCS start>} in target
+ /*
+ * We'll insert it just before the LCS start : there cannot be any common element between the two
+ * lists "before" the LCS since it would be part of the LCS itself.
+ */
+ for (int i = 0; i < target.size() && insertionIndex == -1; i++) {
+ final E targetElement = target.get(i);
+
+ if (equalityHelper.matchingValues(targetElement, firstLCS)) {
+ // We've reached the first element from the LCS in target. Insert here
+ insertionIndex = i;
+ }
+ }
+ return insertionIndex;
+ }
+
+ /**
+ * This will try and determine the index at which a given element from the {@code source} list should be
+ * inserted in the {@code target} list. We expect {@code newElement} to be an element from the
+ * {@code source} or to have a Match that allows us to map it to one of the {@code source} list's
+ * elements.
+ * <p>
+ * The expected insertion index will always be relative to the Longest Common Subsequence (LCS) between
+ * the two given lists. If there are more than one "longest" subsequence between the two lists, the
+ * insertion index will be relative to the first that comes in the {@code target} list.
+ * </p>
+ * <p>
+ * For example, assume {@code source} is <code>{"1", "2", "4", "6", "8", "3", "0", "7", "5"}</code> and
+ * {@code target} is <code>{"8", "1", "2", "9", "3", "4", "7"}</code>; I try to merge the addition of
+ * {@code "0"} in the right list. The returned "insertion index" will be {@code 5} : just after
+ * {@code "3"}. There are two subsequence of the same "longest" length 4 :
+ * <code>{"1", "2", "3", "7"}</code> and <code>{"1", "2", "4", "7"}</code>. However, the first of those
+ * two in {@code target} is <code>{"1", "2", "3", "7"}</code>. The closest element before {@code "0"} in
+ * this LCS in {@code source} is {@code "3"}.
+ * </p>
+ * <p>
+ * Note : we are not using Iterables as input in order to make use of the random access cost of
+ * ArrayLists. This might also be converted to directly use arrays. This implementation will not play well
+ * with LinkedLists or any List which needs to iterate over the values for each call to
+ * {@link List#get(int)}, i.e any list which is not instanceof RandomAccess or does not satisfy its
+ * contract.
+ * </p>
+ *
+ * @param comparison
+ * This will be used in order to retrieve the Match for EObjects when comparing them.
+ * @param source
+ * The List from which one element has to be added to the {@code target} list.
+ * @param target
+ * The List into which one element from {@code source} has to be added.
+ * @param newElement
+ * The element from {@code source} that needs to be added into {@code target}.
+ * @param <E>
+ * Type of the sequences content.
+ * @return The index at which {@code newElement} should be inserted in {@code target}.
+ * @see #longestCommonSubsequence(Comparison, List, List)
+ */
+ public static <E> int findInsertionIndex(Comparison comparison, List<E> source, List<E> target,
+ E newElement) {
+ return findInsertionIndex(comparison, null, source, target, newElement);
+ }
+
+ /**
+ * This is the main entry point for {@link #findInsertionIndex(Comparison, Iterable, List, List, Object)}.
+ * It will use default algorithms to determine the source and target lists as well as the list of elements
+ * that should be ignored when computing the insertion index.
+ *
+ * @param comparison
+ * This will be used in order to retrieve the Match for EObjects when comparing them.
+ * @param diff
+ * The diff which merging will trigger the need for an insertion index in its target list.
+ * @param rightToLeft
+ * {@code true} if the merging will be done into the left list, so that we should consider the
+ * right model as the source and the left as the target.
+ * @return The index at which this {@code diff}'s value should be inserted into the 'target' list, as
+ * inferred from {@code rightToLeft}.
+ * @see #findInsertionIndex(Comparison, Iterable, List, List, Object)
+ */
+ @SuppressWarnings("unchecked")
+ public static int findInsertionIndex(Comparison comparison, Diff diff, boolean rightToLeft) {
+ final EStructuralFeature feature;
+ final Object value;
+ if (diff instanceof AttributeChange) {
+ feature = ((AttributeChange)diff).getAttribute();
+ value = ((AttributeChange)diff).getValue();
+ } else if (diff instanceof ReferenceChange) {
+ feature = ((ReferenceChange)diff).getReference();
+ value = ((ReferenceChange)diff).getValue();
+ } else {
+ throw new IllegalArgumentException(EMFCompareMessages.getString(
+ "DiffUtil.IllegalDiff", diff.eClass().getName())); //$NON-NLS-1$
+ }
+ if (!feature.isMany()) {
+ throw new IllegalArgumentException(EMFCompareMessages.getString(
+ "DiffUtil.IllegalFeature", feature.getName())); //$NON-NLS-1$
+ }
+ final Match match = diff.getMatch();
+
+ final EObject expectedContainer;
+ if (feature instanceof EReference && ((EReference)feature).isContainment()
+ && diff.getKind() == DifferenceKind.MOVE) {
+ // The value can only be an EObject, and its match cannot be null.
+ // If any of these two assumptions is wrong, something went horribly awry beforehand.
+ final Match valueMatch = comparison.getMatch((EObject)value);
+
+ final Match targetContainerMatch;
+ // If it exists, use the source side's container as reference
+ if (rightToLeft && valueMatch.getRight() != null) {
+ targetContainerMatch = comparison.getMatch(valueMatch.getRight().eContainer());
+ } else if (!rightToLeft && valueMatch.getLeft() != null) {
+ targetContainerMatch = comparison.getMatch(valueMatch.getLeft().eContainer());
+ } else {
+ // Otherwise, the value we're moving on one side has been removed from its source side.
+ targetContainerMatch = comparison.getMatch(valueMatch.getOrigin().eContainer());
+ }
+ if (rightToLeft) {
+ expectedContainer = targetContainerMatch.getLeft();
+ } else {
+ expectedContainer = targetContainerMatch.getRight();
+ }
+ } else if (rightToLeft) {
+ expectedContainer = match.getLeft();
+ } else {
+ expectedContainer = match.getRight();
+ }
+
+ final List<Object> sourceList = getSourceList(diff, feature, rightToLeft);
+ final List<Object> targetList;
+
+ if (expectedContainer != null) {
+ final List<Object> temp = (List<Object>)ReferenceUtil.safeEGet(expectedContainer, feature);
+ if (feature == EcorePackage.Literals.ECLASS__ESUPER_TYPES
+ || feature == EcorePackage.Literals.EOPERATION__EEXCEPTIONS) {
+ // workaround 394286
+ targetList = temp;
+ } else if (temp instanceof InternalEList<?>) {
+ // EMF ignores the "resolve" flag for containment lists...
+ targetList = ((InternalEList<Object>)temp).basicList();
+ } else {
+ targetList = temp;
+ }
+ } else {
+ targetList = ImmutableList.of();
+ }
+
+ Iterable<Object> ignoredElements = Iterables.concat(computeIgnoredElements(targetList, diff),
+ Collections.singleton(value));
+ // We know we'll have to iterate quite a number of times on this one.
+ ignoredElements = Lists.newArrayList(ignoredElements);
+
+ return DiffUtil.findInsertionIndex(comparison, ignoredElements, sourceList, targetList, value);
+ }
+
+ /**
+ * Retrieves the "source" list of the given {@code diff}. This will be different according to the kind of
+ * change and the direction of the merging.
+ *
+ * @param diff
+ * The diff for which merging we need a 'source'.
+ * @param feature
+ * The feature on which the merging is actually taking place.
+ * @param rightToLeft
+ * Direction of the merging. {@code true} if the merge is to be done on the left side, making
+ * 'source' the right side, {@code false} otherwise.
+ * @return The list that should be used as a source for this merge. May be empty, but never
+ * <code>null</code>.
+ */
+ @SuppressWarnings("unchecked")
+ private static List<Object> getSourceList(Diff diff, EStructuralFeature feature, boolean rightToLeft) {
+ final Match match = diff.getMatch();
+ final List<Object> sourceList;
+ final EObject expectedContainer;
+
+ if (diff.getKind() == DifferenceKind.MOVE) {
+ final boolean undoingLeft = rightToLeft && diff.getSource() == DifferenceSource.LEFT;
+ final boolean undoingRight = !rightToLeft && diff.getSource() == DifferenceSource.RIGHT;
+
+ if ((undoingLeft || undoingRight) && match.getOrigin() != null) {
+ expectedContainer = match.getOrigin();
+ } else if (rightToLeft) {
+ expectedContainer = match.getRight();
+ } else {
+ expectedContainer = match.getLeft();
+ }
+
+ } else {
+ if (match.getOrigin() != null && diff.getKind() == DifferenceKind.DELETE) {
+ expectedContainer = match.getOrigin();
+ } else if (rightToLeft) {
+ expectedContainer = match.getRight();
+ } else {
+ expectedContainer = match.getLeft();
+ }
+ }
+
+ if (expectedContainer != null) {
+ final List<Object> temp = (List<Object>)ReferenceUtil.safeEGet(expectedContainer, feature);
+ if (feature == EcorePackage.Literals.ECLASS__ESUPER_TYPES
+ || feature == EcorePackage.Literals.EOPERATION__EEXCEPTIONS) {
+ // workaround 394286
+ sourceList = temp;
+ } else if (temp instanceof InternalEList<?>) {
+ // EMF ignores the "resolve" flag for containment lists...
+ sourceList = ((InternalEList<Object>)temp).basicList();
+ } else {
+ sourceList = temp;
+ }
+ } else {
+ sourceList = ImmutableList.of();
+ }
+
+ return sourceList;
+ }
+
+ /**
+ * When computing the insertion index of an element in a list, we need to ignore all elements present in
+ * that list that feature unresolved Diffs on the same feature.
+ *
+ * @param candidates
+ * The sequence in which we need to compute an insertion index.
+ * @param diff
+ * The diff we are computing an insertion index for.
+ * @param <E>
+ * Type of the list's content.
+ * @return The list of elements that should be ignored when computing the insertion index for a new
+ * element in {@code candidates}.
+ */
+ private static <E> Iterable<E> computeIgnoredElements(Iterable<E> candidates, final Diff diff) {
+ final Match match = diff.getMatch();
+ final Iterable<? extends Diff> filteredCandidates = Lists.newArrayList(match.getDifferences());
+ final EStructuralFeature feature;
+ if (diff instanceof AttributeChange) {
+ feature = ((AttributeChange)diff).getAttribute();
+ } else if (diff instanceof ReferenceChange) {
+ feature = ((ReferenceChange)diff).getReference();
+ } else {
+ return Collections.emptyList();
+ }
+
+ final Set<E> ignored = Sets.newLinkedHashSet();
+ for (E candidate : candidates) {
+ if (candidate instanceof EObject) {
+ final Iterable<? extends Diff> differences = match.getComparison().getDifferences(
+ (EObject)candidate);
+ if (Iterables.any(differences, new UnresolvedDiffMatching(feature, candidate))) {
+ ignored.add(candidate);
+ }
+ } else {
+ if (Iterables.any(filteredCandidates, new UnresolvedDiffMatching(feature, candidate))) {
+ ignored.add(candidate);
+ }
+ }
+ }
+ return ignored;
+ }
+
+ /**
+ * This can be used to check whether a given Diff affects a value for which we can find another,
+ * unresolved Diff on a given Feature.
+ *
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+ private static class UnresolvedDiffMatching implements Predicate<Diff> {
+ /** Feature on which we expect an unresolved diff. */
+ private final EStructuralFeature feature;
+
+ /** Element for which we expect an unresolved diff. */
+ private final Object element;
+
+ /**
+ * Constructs a predicate that can be used to retrieve all unresolved diffs that apply to the given
+ * {@code feature} and {@code element}.
+ *
+ * @param feature
+ * The feature which our diffs must concern.
+ * @param element
+ * The element which must be our diffs' target.
+ */
+ public UnresolvedDiffMatching(EStructuralFeature feature, Object element) {
+ this.feature = feature;
+ this.element = element;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see com.google.common.base.Predicate#apply(java.lang.Object)
+ */
+ public boolean apply(Diff input) {
+ boolean apply = false;
+ if (input instanceof AttributeChange) {
+ apply = input.getState() == DifferenceState.UNRESOLVED
+ && ((AttributeChange)input).getAttribute() == feature
+ && matchingValues((AttributeChange)input, element);
+ } else if (input instanceof ReferenceChange) {
+ apply = input.getState() == DifferenceState.UNRESOLVED
+ && ((ReferenceChange)input).getReference() == feature
+ && matchingValues((ReferenceChange)input, element);
+ } else {
+ apply = false;
+ }
+ return apply;
+ }
+
+ /**
+ * Checks that the value of the given diff matches <code>value</code>, resorting to the equality
+ * helper if needed.
+ *
+ * @param diff
+ * The diff which value we need to check.
+ * @param value
+ * The expected value of <code>diff</code>
+ * @return <code>true</code> if the value matches.
+ */
+ private boolean matchingValues(AttributeChange diff, Object value) {
+ if (diff.getValue() == value) {
+ return true;
+ }
+ // Only resort to the equality helper as "last resort"
+ final IEqualityHelper helper = diff.getMatch().getComparison().getEqualityHelper();
+ return helper.matchingAttributeValues(diff.getValue(), value);
+ }
+
+ /**
+ * Checks that the value of the given diff matches <code>value</code>, resorting to the equality
+ * helper if needed.
+ *
+ * @param diff
+ * The diff which value we need to check.
+ * @param value
+ * The expected value of <code>diff</code>
+ * @return <code>true</code> if the value matches.
+ */
+ private boolean matchingValues(ReferenceChange diff, Object value) {
+ if (diff.getValue() == value) {
+ return true;
+ }
+ // Only resort to the equality helper as "last resort"
+ final IEqualityHelper helper = diff.getMatch().getComparison().getEqualityHelper();
+ return helper.matchingValues(diff.getValue(), value);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/eobject/EditionDistance.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/eobject/EditionDistance.java
index 2d3a18904..0fa434349 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/eobject/EditionDistance.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/eobject/EditionDistance.java
@@ -31,11 +31,11 @@ import org.eclipse.emf.compare.diff.DefaultDiffEngine;
import org.eclipse.emf.compare.diff.FeatureFilter;
import org.eclipse.emf.compare.diff.IDiffProcessor;
import org.eclipse.emf.compare.internal.spec.ComparisonSpec;
+import org.eclipse.emf.compare.internal.utils.DiffUtil;
import org.eclipse.emf.compare.match.DefaultEqualityHelperFactory;
import org.eclipse.emf.compare.match.IEqualityHelperFactory;
import org.eclipse.emf.compare.match.eobject.ProximityEObjectMatcher.DistanceFunction;
import org.eclipse.emf.compare.match.eobject.internal.ReflectiveWeightProvider;
-import org.eclipse.emf.compare.utils.DiffUtil;
import org.eclipse.emf.compare.utils.EqualityHelper;
import org.eclipse.emf.compare.utils.IEqualityHelper;
import org.eclipse.emf.compare.utils.ReferenceUtil;
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/resource/NameSimilarityMatchingStrategy.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/resource/NameSimilarityMatchingStrategy.java
index a70f0ac6c..4233b0a0a 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/resource/NameSimilarityMatchingStrategy.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/resource/NameSimilarityMatchingStrategy.java
@@ -22,7 +22,7 @@ import java.util.Set;
import org.eclipse.emf.compare.CompareFactory;
import org.eclipse.emf.compare.MatchResource;
-import org.eclipse.emf.compare.utils.DiffUtil;
+import org.eclipse.emf.compare.internal.utils.DiffUtil;
import org.eclipse.emf.ecore.resource.Resource;
/**
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AttributeChangeMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AttributeChangeMerger.java
index c99adc317..0a165b5f9 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AttributeChangeMerger.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AttributeChangeMerger.java
@@ -23,7 +23,7 @@ import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.DifferenceSource;
import org.eclipse.emf.compare.DifferenceState;
import org.eclipse.emf.compare.Match;
-import org.eclipse.emf.compare.utils.DiffUtil;
+import org.eclipse.emf.compare.internal.utils.DiffUtil;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ReferenceChangeMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ReferenceChangeMerger.java
index 398c33963..f77eef08e 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ReferenceChangeMerger.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ReferenceChangeMerger.java
@@ -12,6 +12,9 @@ package org.eclipse.emf.compare.merge;
import static org.eclipse.emf.compare.utils.ReferenceUtil.safeEIsSet;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+
import java.util.Iterator;
import java.util.List;
@@ -23,7 +26,7 @@ import org.eclipse.emf.compare.DifferenceSource;
import org.eclipse.emf.compare.DifferenceState;
import org.eclipse.emf.compare.Match;
import org.eclipse.emf.compare.ReferenceChange;
-import org.eclipse.emf.compare.utils.DiffUtil;
+import org.eclipse.emf.compare.internal.utils.DiffUtil;
import org.eclipse.emf.compare.utils.IEqualityHelper;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
@@ -61,83 +64,27 @@ public class ReferenceChangeMerger extends AbstractMerger {
// Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
diff.setState(DifferenceState.MERGED);
- if (diff.getEquivalence() != null) {
- boolean continueMerge = handleEquivalences(diff, false, monitor);
- if (!continueMerge) {
- return;
- }
- }
if (diff.getSource() == DifferenceSource.LEFT) {
// merge all "requires" diffs
mergeRequires(diff, false, monitor);
-
- switch (diff.getKind()) {
- case ADD:
- // Create the same element in right
- addInTarget(diff, false);
- break;
- case DELETE:
- // Delete that same element from right
- removeFromTarget(diff, false);
- break;
- case MOVE:
- moveElement(diff, false);
- break;
- case CHANGE:
- // Is it an unset?
- if (diff.getMatch().getLeft() != null) {
- final EObject leftValue = (EObject)diff.getMatch().getLeft().eGet(
- diff.getReference(), false);
- if (leftValue == null) {
- removeFromTarget(diff, false);
- } else {
- addInTarget(diff, false);
- }
- } else {
- // we have no left, and the source is on the left. Can only be an unset
- removeFromTarget(diff, false);
- }
- break;
- default:
- break;
- }
+ handleImplies(diff, false, monitor);
} else {
// merge all "required by" diffs
mergeRequiredBy(diff, false, monitor);
+ handleImpliedBy(diff, false, monitor);
+ }
- switch (diff.getKind()) {
- case ADD:
- // We have a ADD on right. we need to revert this addition
- removeFromTarget(diff, false);
- break;
- case DELETE:
- // DELETE in the right. We need to re-create this element
- addInTarget(diff, false);
- break;
- case MOVE:
- moveElement(diff, false);
- break;
- case CHANGE:
- // Is it an unset?
- if (diff.getMatch().getRight() != null) {
- final EObject rightValue = (EObject)diff.getMatch().getRight().eGet(
- diff.getReference(), false);
- if (rightValue == null) {
- // Value has been unset in the right, and we are merging towards right.
- // We need to re-add this element
- addInTarget(diff, false);
- } else {
- // We'll actually need to "reset" this reference to its original value
- resetInTarget(diff, false);
- }
- } else {
- // we have no right, and the source is on the right. Can only be an unset
- addInTarget(diff, false);
- }
- break;
- default:
- break;
+ boolean hasToBeMerged = true;
+ if (diff.getEquivalence() != null) {
+ hasToBeMerged = handleEquivalences(diff, false, monitor);
+ }
+
+ if (hasToBeMerged) {
+ if (diff.getSource() == DifferenceSource.LEFT) {
+ accept(diff, false);
+ } else {
+ reject(diff, false);
}
}
}
@@ -157,82 +104,160 @@ public class ReferenceChangeMerger extends AbstractMerger {
// Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
diff.setState(DifferenceState.MERGED);
- if (diff.getEquivalence() != null) {
- boolean continueMerge = handleEquivalences(diff, true, monitor);
- if (!continueMerge) {
- return;
- }
- }
if (diff.getSource() == DifferenceSource.LEFT) {
// merge all "required by" diffs
mergeRequiredBy(diff, true, monitor);
-
- switch (diff.getKind()) {
- case ADD:
- // We have a ADD on left, thus nothing in right. We need to revert the addition
- removeFromTarget(diff, true);
- break;
- case DELETE:
- // DELETE in the left, thus an element in right. We need to re-create that element
- addInTarget(diff, true);
- break;
- case MOVE:
- moveElement(diff, true);
- break;
- case CHANGE:
- // Is it an unset?
- if (diff.getMatch().getLeft() != null) {
- final EObject leftValue = (EObject)diff.getMatch().getLeft().eGet(
- diff.getReference(), false);
- if (leftValue == null) {
- // Value has been unset in the right, and we are merging towards right.
- // We need to re-add this element
- addInTarget(diff, true);
- } else {
- // We'll actually need to "reset" this reference to its original value
- resetInTarget(diff, true);
- }
- } else {
- // we have no left, and the source is on the left. Can only be an unset
- addInTarget(diff, true);
- }
- break;
- default:
- break;
- }
+ handleImpliedBy(diff, true, monitor);
} else {
// merge all "requires" diffs
mergeRequires(diff, true, monitor);
+ handleImplies(diff, true, monitor);
+ }
+
+ boolean hasToBeMerged = true;
+ if (diff.getEquivalence() != null) {
+ hasToBeMerged = handleEquivalences(diff, true, monitor);
+ }
+
+ if (hasToBeMerged) {
+ if (diff.getSource() == DifferenceSource.LEFT) {
+ reject(diff, true);
+ } else {
+ accept(diff, true);
+ }
+ }
+ }
+
+ /**
+ * Merge the given difference rejecting it.
+ *
+ * @param diff
+ * The difference to merge.
+ * @param rightToLeft
+ * The direction of the merge.
+ */
+ private void reject(final ReferenceChange diff, boolean rightToLeft) {
+ DifferenceSource source = diff.getSource();
+ switch (diff.getKind()) {
+ case ADD:
+ // We have a ADD on left, thus nothing in right. We need to revert the addition
+ removeFromTarget(diff, rightToLeft);
+ break;
+ case DELETE:
+ // DELETE in the left, thus an element in right. We need to re-create that element
+ addInTarget(diff, rightToLeft);
+ break;
+ case MOVE:
+ moveElement(diff, rightToLeft);
+ break;
+ case CHANGE:
+ EObject container = null;
+ if (source == DifferenceSource.LEFT) {
+ container = diff.getMatch().getLeft();
- switch (diff.getKind()) {
- case ADD:
- addInTarget(diff, true);
- break;
- case DELETE:
- removeFromTarget(diff, true);
- break;
- case MOVE:
- moveElement(diff, true);
- break;
- case CHANGE:
- // Is it an unset?
- if (diff.getMatch().getRight() != null) {
- final EObject rightValue = (EObject)diff.getMatch().getRight().eGet(
- diff.getReference(), false);
- if (rightValue == null) {
- removeFromTarget(diff, true);
- } else {
- addInTarget(diff, true);
- }
+ } else {
+ container = diff.getMatch().getRight();
+ }
+ // Is it an unset?
+ if (container != null) {
+ final EObject leftValue = (EObject)container.eGet(diff.getReference(), false);
+ if (leftValue == null) {
+ // Value has been unset in the right, and we are merging towards right.
+ // We need to re-add this element
+ addInTarget(diff, rightToLeft);
} else {
- // we have no right, and the source is on the right. Can only be an unset
- removeFromTarget(diff, true);
+ // We'll actually need to "reset" this reference to its original value
+ resetInTarget(diff, rightToLeft);
}
- break;
- default:
- break;
- }
+ } else {
+ // we have no left, and the source is on the left. Can only be an unset
+ addInTarget(diff, rightToLeft);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Merge the given difference accepting it.
+ *
+ * @param diff
+ * The difference to merge.
+ * @param rightToLeft
+ * The direction of the merge.
+ */
+ private void accept(final ReferenceChange diff, boolean rightToLeft) {
+ DifferenceSource source = diff.getSource();
+ switch (diff.getKind()) {
+ case ADD:
+ // Create the same element in right
+ addInTarget(diff, rightToLeft);
+ break;
+ case DELETE:
+ // Delete that same element from right
+ removeFromTarget(diff, rightToLeft);
+ break;
+ case MOVE:
+ moveElement(diff, rightToLeft);
+ break;
+ case CHANGE:
+ EObject container = null;
+ if (source == DifferenceSource.LEFT) {
+ container = diff.getMatch().getLeft();
+ } else {
+ container = diff.getMatch().getRight();
+ }
+ // Is it an unset?
+ if (container != null) {
+ final EObject leftValue = (EObject)container.eGet(diff.getReference(), false);
+ if (leftValue == null) {
+ removeFromTarget(diff, rightToLeft);
+ } else {
+ addInTarget(diff, rightToLeft);
+ }
+ } else {
+ // we have no left, and the source is on the left. Can only be an unset
+ removeFromTarget(diff, rightToLeft);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Mark as MERGED all the implied differences recursively from the given one.
+ *
+ * @param diff
+ * The difference from which the implications have to be marked.
+ * @param rightToLeft
+ * The direction of the merge.
+ * @param monitor
+ * Monitor.
+ */
+ private void handleImplies(Diff diff, boolean rightToLeft, Monitor monitor) {
+ for (Diff implied : diff.getImplies()) {
+ implied.setState(DifferenceState.MERGED);
+ handleImplies(implied, rightToLeft, monitor);
+ }
+ }
+
+ /**
+ * Mark as MERGED all the implying differences recursively from the given one.
+ *
+ * @param diff
+ * The difference from which the implications have to be marked.
+ * @param rightToLeft
+ * The direction of the merge.
+ * @param monitor
+ * Monitor.
+ */
+ private void handleImpliedBy(Diff diff, boolean rightToLeft, Monitor monitor) {
+ for (Diff impliedBy : diff.getImpliedBy()) {
+ impliedBy.setState(DifferenceState.MERGED);
+ handleImpliedBy(impliedBy, rightToLeft, monitor);
}
}
@@ -621,6 +646,7 @@ public class ReferenceChangeMerger extends AbstractMerger {
final EReference reference = diff.getReference();
boolean continueMerge = true;
for (Diff equivalent : diff.getEquivalence().getDifferences()) {
+ // For 1..*, merge diff on many-valued to preserve ordering
if (equivalent instanceof ReferenceChange
&& reference.getEOpposite() == ((ReferenceChange)equivalent).getReference()
&& equivalent.getState() == DifferenceState.UNRESOLVED) {
@@ -631,39 +657,52 @@ public class ReferenceChangeMerger extends AbstractMerger {
mergeDiff(equivalent, rightToLeft, monitor);
continueMerge = false;
}
- } else if (diff.getSource() == DifferenceSource.LEFT) {
- // This can happen when merging subset/supersets... see AddInterfaceTest#testA50UseCase
- /*
- * This should be removed (or we should make sure that we can never be here) when bug 398402
- * is fixed.
- */
- if (rightToLeft && diff.getRequiredBy().contains(equivalent)) {
- mergeDiff(equivalent, rightToLeft, monitor);
- continueMerge = false;
- } else if (!rightToLeft && diff.getRequires().contains(equivalent)) {
- mergeDiff(equivalent, rightToLeft, monitor);
- continueMerge = false;
+ }
+
+ /*
+ * If one of the equivalent differences is implied or implying (depending on the merge direction)
+ * a merged diff, then we have a dependency loop : the "current" difference has already been
+ * merged because of this implication. This will allow us to break out of that loop.
+ */
+ if (rightToLeft) {
+ if (diff.getSource() == DifferenceSource.LEFT) {
+ continueMerge = continueMerge
+ && !containsAny(diff.getRequiredBy(), equivalent.getImplies());
+ } else {
+ continueMerge = continueMerge
+ && !containsAny(diff.getRequires(), equivalent.getImpliedBy());
}
- } else if (diff.getSource() == DifferenceSource.RIGHT) {
- // This can happen when merging subset/supersets... see AddInterfaceTest#testA50UseCase
- /*
- * This should be removed (or we should make sure that we can never be here) when bug 398402
- * is fixed.
- */
- if (rightToLeft && diff.getRequires().contains(equivalent)) {
- mergeDiff(equivalent, rightToLeft, monitor);
- continueMerge = false;
- } else if (!rightToLeft && diff.getRequiredBy().contains(equivalent)) {
- mergeDiff(equivalent, rightToLeft, monitor);
- continueMerge = false;
+ } else {
+ if (diff.getSource() == DifferenceSource.LEFT) {
+ continueMerge = continueMerge
+ && !containsAny(diff.getRequires(), equivalent.getImpliedBy());
+ } else {
+ continueMerge = continueMerge
+ && !containsAny(diff.getRequiredBy(), equivalent.getImplies());
}
}
+
equivalent.setState(DifferenceState.MERGED);
}
return continueMerge;
}
/**
+ * Utility method to check that the first sequence contains one of the elements of the second sequence at
+ * least.
+ *
+ * @param sequence1
+ * The first sequence.
+ * @param sequence2
+ * The second sequence.
+ * @return True if the given first sequence contains one of the elements of the second sequence at least.
+ * false otherwise.
+ */
+ private boolean containsAny(List<? extends EObject> sequence1, List<? extends EObject> sequence2) {
+ return Iterables.any(sequence2, Predicates.in(sequence1));
+ }
+
+ /**
* Seeks a match of the given {@code element} in the given list, using the equality helper to find it.
* This is only used when moving or deleting proxies for now.
*
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ResourceAttachmentChangeMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ResourceAttachmentChangeMerger.java
index 1758fcf7d..8b742a253 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ResourceAttachmentChangeMerger.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ResourceAttachmentChangeMerger.java
@@ -23,7 +23,7 @@ import org.eclipse.emf.compare.EMFCompareMessages;
import org.eclipse.emf.compare.Match;
import org.eclipse.emf.compare.MatchResource;
import org.eclipse.emf.compare.ResourceAttachmentChange;
-import org.eclipse.emf.compare.utils.DiffUtil;
+import org.eclipse.emf.compare.internal.utils.DiffUtil;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/req/DefaultReqEngine.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/req/DefaultReqEngine.java
index b0f48a8c3..4c17586d9 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/req/DefaultReqEngine.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/req/DefaultReqEngine.java
@@ -13,6 +13,8 @@ package org.eclipse.emf.compare.req;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.collect.Iterables.filter;
+import static org.eclipse.emf.compare.internal.utils.ComparisonUtil.isAddOrSetDiff;
+import static org.eclipse.emf.compare.internal.utils.ComparisonUtil.isDeleteOrUnsetDiff;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.ofKind;
import com.google.common.base.Predicate;
@@ -27,7 +29,6 @@ import org.eclipse.emf.common.util.Monitor;
import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.DifferenceKind;
-import org.eclipse.emf.compare.DifferenceSource;
import org.eclipse.emf.compare.Match;
import org.eclipse.emf.compare.ReferenceChange;
import org.eclipse.emf.compare.ResourceAttachmentChange;
@@ -77,8 +78,11 @@ public class DefaultReqEngine implements IReqEngine {
DifferenceKind kind = difference.getKind();
if (value != null) {
+ boolean isAddition = isAddOrSetDiff(difference);
+ boolean isDeletion = !isAddition && isDeleteOrUnsetDiff(difference);
+
// ADD object
- if (kind == DifferenceKind.ADD && isContainment(difference)) {
+ if (isAddition && isContainment(difference)) {
// -> requires ADD on the container of the object
requiredDifferences.addAll(getDifferenceOnGivenObject(comparison, value.eContainer(),
@@ -88,8 +92,7 @@ public class DefaultReqEngine implements IReqEngine {
requiredDifferences.addAll(getDELOriginValueOnContainmentRefSingle(comparison, difference));
// ADD reference
- } else if ((kind == DifferenceKind.ADD || isChangeAdd(comparison, difference))
- && !isContainment(difference)) {
+ } else if (isAddition) {
// -> requires ADD of the value of the reference (target object)
requiredDifferences.addAll(getDifferenceOnGivenObject(comparison, value, DifferenceKind.ADD));
@@ -104,7 +107,7 @@ public class DefaultReqEngine implements IReqEngine {
instanceOf(ResourceAttachmentChange.class), ofKind(DifferenceKind.ADD))));
// DELETE object
- } else if (kind == DifferenceKind.DELETE && isContainment(difference)) {
+ } else if (isDeletion && isContainment(difference)) {
// -> requires DELETE of the outgoing references and contained objects
requiredDifferences.addAll(getDELOutgoingReferences(comparison, difference));
@@ -118,8 +121,7 @@ public class DefaultReqEngine implements IReqEngine {
// reference cases.
// DELETE reference
- } else if ((kind == DifferenceKind.DELETE || isChangeDelete(difference))
- && !isContainment(difference)) {
+ } else if (isDeletion) {
// -> is required by DELETE of the target object
requiredByDifferences.addAll(getDifferenceOnGivenObject(comparison, value,
@@ -139,8 +141,7 @@ public class DefaultReqEngine implements IReqEngine {
DifferenceKind.MOVE));
// CHANGE reference
- } else if (kind == DifferenceKind.CHANGE && !isChangeAdd(comparison, difference)
- && !isChangeDelete(difference)) {
+ } else if (kind == DifferenceKind.CHANGE && !isAddition && !isDeletion) {
// -> is required by DELETE of the origin target object
requiredByDifferences.addAll(getDifferenceOnGivenObject(comparison, MatchUtil.getOriginValue(
@@ -276,7 +277,7 @@ public class DefaultReqEngine implements IReqEngine {
final Match valueMatch = comparison.getMatch(value);
if (valueMatch != null) {
for (ReferenceChange candidate : filter(valueMatch.getDifferences(), ReferenceChange.class)) {
- if (candidate.getKind() == DifferenceKind.DELETE || isChangeDelete(candidate)) {
+ if (candidate.getKind() == DifferenceKind.DELETE || isDeleteOrUnsetDiff(candidate)) {
result.add(candidate);
}
}
@@ -319,59 +320,6 @@ public class DefaultReqEngine implements IReqEngine {
}
/**
- * Check if the given <code>difference</code> is a CHANGE from a null value on a mono-valued reference.
- *
- * @param comparison
- * The comparison this engine is expected to complete.
- * @param difference
- * The given difference.
- * @return True if it is a CHANGE from a null value.
- */
- private static boolean isChangeAdd(Comparison comparison, Diff difference) {
- boolean result = false;
- if (difference instanceof ReferenceChange) {
- EReference reference = ((ReferenceChange)difference).getReference();
- if (!reference.isMany() && !reference.isContainment()) {
- Match match = difference.getMatch();
- if (comparison.isThreeWay()) {
- final EObject origin = match.getOrigin();
- result = origin == null || ReferenceUtil.safeEGet(origin, reference) == null;
- } else {
- // two way can't have "remote" diffs. This is an addition if right is null
- final EObject right = match.getRight();
- result = right == null || ReferenceUtil.safeEGet(right, reference) == null;
- }
- }
- }
- return result;
- }
-
- /**
- * Check if the given <code>difference</code> is a CHANGE to a null value on a mono-valued reference.
- *
- * @param difference
- * The given difference.
- * @return True if it is a CHANGE to a null value.
- */
- private static boolean isChangeDelete(Diff difference) {
- boolean result = false;
- if (difference instanceof ReferenceChange) {
- EReference reference = ((ReferenceChange)difference).getReference();
- if (!reference.isMany() && !reference.isContainment()) {
- Match match = difference.getMatch();
- if (difference.getSource() == DifferenceSource.LEFT) {
- final EObject left = match.getLeft();
- result = left == null || ReferenceUtil.safeEGet(left, reference) == null;
- } else {
- final EObject right = match.getRight();
- result = right == null || ReferenceUtil.safeEGet(right, reference) == null;
- }
- }
- }
- return result;
- }
-
- /**
* Checks whether the given diff corresponds to a containment change. This holds true for differences on
* containment references' values, but also for resource attachment changes.
*
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/DiffUtil.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/DiffUtil.java
index 0a0bed18c..97a4ab054 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/DiffUtil.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/DiffUtil.java
@@ -10,49 +10,22 @@
*******************************************************************************/
package org.eclipse.emf.compare.utils;
-import static com.google.common.collect.Iterables.addAll;
-import static com.google.common.collect.Iterables.concat;
-
import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.HashMultiset;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Multiset;
-import com.google.common.collect.Sets;
-import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
import java.util.List;
-import java.util.ListIterator;
-import java.util.Set;
-import org.eclipse.emf.compare.AttributeChange;
import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.Diff;
-import org.eclipse.emf.compare.DifferenceKind;
-import org.eclipse.emf.compare.DifferenceSource;
-import org.eclipse.emf.compare.DifferenceState;
-import org.eclipse.emf.compare.EMFCompareMessages;
-import org.eclipse.emf.compare.Match;
-import org.eclipse.emf.compare.ReferenceChange;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.EcorePackage;
-import org.eclipse.emf.ecore.util.InternalEList;
+import org.eclipse.emf.compare.internal.utils.ComparisonUtil;
/**
* This utility class will be used to provide similarity implementations.
*
* @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ * @deprecated Not intendended to be used by clients
*/
+@Deprecated
public final class DiffUtil {
/** This utility class does not need to be instantiated. */
private DiffUtil() {
@@ -72,46 +45,7 @@ public final class DiffUtil {
* @return The dice coefficient of the two given String's bigrams, ranging from 0 to 1.
*/
public static double diceCoefficient(String first, String second) {
- final char[] str1 = first.toCharArray();
- final char[] str2 = second.toCharArray();
-
- final double coefficient;
-
- if (Arrays.equals(str1, str2)) {
- coefficient = 1d;
- } else if (str1.length <= 2 || str2.length <= 2) {
- int equalChars = 0;
-
- for (int i = 0; i < Math.min(str1.length, str2.length); i++) {
- if (str1[i] == str2[i]) {
- equalChars++;
- }
- }
-
- int union = str1.length + str2.length;
- if (str1.length != str2.length) {
- coefficient = (double)equalChars / union;
- } else {
- coefficient = ((double)equalChars * 2) / union;
- }
- } else {
- Set<String> s1Bigrams = Sets.newHashSet();
- Set<String> s2Bigrams = Sets.newHashSet();
-
- for (int i = 0; i < str1.length - 1; i++) {
- char[] chars = new char[] {str1[i], str1[i + 1], };
- s1Bigrams.add(String.valueOf(chars));
- }
- for (int i = 0; i < str2.length - 1; i++) {
- char[] chars = new char[] {str2[i], str2[i + 1], };
- s2Bigrams.add(String.valueOf(chars));
- }
-
- Set<String> intersection = Sets.intersection(s1Bigrams, s2Bigrams);
- coefficient = (2d * intersection.size()) / (s1Bigrams.size() + s2Bigrams.size());
- }
-
- return coefficient;
+ return org.eclipse.emf.compare.internal.utils.DiffUtil.diceCoefficient(first, second);
}
/**
@@ -149,23 +83,8 @@ public final class DiffUtil {
*/
public static <E> List<E> longestCommonSubsequence(Comparison comparison, Iterable<E> ignoredElements,
List<E> sequence1, List<E> sequence2) {
- final List<E> copy1 = Lists.newArrayList(sequence1);
- final List<E> copy2 = Lists.newArrayList(sequence2);
-
- // Reduce sets
- final List<E> prefix = trimPrefix(comparison, ignoredElements, copy1, copy2);
- final List<E> suffix = trimSuffix(comparison, ignoredElements, copy1, copy2);
-
- final List<E> subLCS;
- // FIXME extract an interface for the LCS and properly separate these two differently typed
- // implementations.
- if (copy1.size() > Short.MAX_VALUE || copy2.size() > Short.MAX_VALUE) {
- subLCS = intLongestCommonSubsequence(comparison, ignoredElements, copy1, copy2);
- } else {
- subLCS = shortLongestCommonSubsequence(comparison, ignoredElements, copy1, copy2);
- }
-
- return ImmutableList.copyOf(Iterables.concat(prefix, subLCS, suffix));
+ return org.eclipse.emf.compare.internal.utils.DiffUtil.longestCommonSubsequence(comparison,
+ ignoredElements, sequence1, sequence2);
}
/**
@@ -208,300 +127,11 @@ public final class DiffUtil {
*/
public static <E> List<E> longestCommonSubsequence(Comparison comparison, List<E> sequence1,
List<E> sequence2) {
- return longestCommonSubsequence(comparison, Collections.<E> emptyList(), sequence1, sequence2);
- }
-
- /**
- * Trims and returns the common prefix of the two given sequences. All ignored elements within or after
- * this common prefix will also be trimmed.
- * <p>
- * Note that the two given sequences will be modified in-place.
- * </p>
- *
- * @param comparison
- * This will be used in order to retrieve the Match for EObjects when comparing them.
- * @param ignoredElements
- * Specifies elements that should be excluded from the subsequences.
- * @param sequence1
- * First of the two sequences to consider.
- * @param sequence2
- * Second of the two sequences to consider.
- * @param <E>
- * Type of the sequences content.
- * @return The common prefix of the two given sequences, less their ignored elements. As a side note, both
- * {@code sequence1} and {@code sequence2} will have been trimmed of their prefix when this
- * returns.
- */
- private static <E> List<E> trimPrefix(Comparison comparison, Iterable<E> ignoredElements,
- List<E> sequence1, List<E> sequence2) {
- final IEqualityHelper equalityHelper = comparison.getEqualityHelper();
- final int size1 = sequence1.size();
- final int size2 = sequence2.size();
-
- final List<E> prefix = Lists.newArrayList();
- int start1 = 1;
- int start2 = 1;
- boolean matching = true;
- while (start1 <= size1 && start2 <= size2 && matching) {
- final E first = sequence1.get(start1 - 1);
- final E second = sequence2.get(start2 - 1);
- if (equalityHelper.matchingValues(first, second)) {
- prefix.add(first);
- start1++;
- start2++;
- } else {
- boolean ignore1 = contains(comparison, equalityHelper, ignoredElements, first);
- boolean ignore2 = contains(comparison, equalityHelper, ignoredElements, second);
- if (ignore1) {
- start1++;
- }
- if (ignore2) {
- start2++;
- }
- if (!ignore1 && !ignore2) {
- matching = false;
- }
- }
- }
- sequence1.subList(0, start1 - 1).clear();
- sequence2.subList(0, start2 - 1).clear();
-
- return prefix;
- }
-
- /**
- * Trims and returns the common suffix of the two given sequences. All ignored elements within or before
- * this common suffix will also be trimmed.
- * <p>
- * Note that the two given sequences will be modified in-place.
- * </p>
- *
- * @param comparison
- * This will be used in order to retrieve the Match for EObjects when comparing them.
- * @param ignoredElements
- * Specifies elements that should be excluded from the subsequences.
- * @param sequence1
- * First of the two sequences to consider.
- * @param sequence2
- * Second of the two sequences to consider.
- * @param <E>
- * Type of the sequences content.
- * @return The common suffix of the two given sequences, less their ignored elements. As a side note, both
- * {@code sequence1} and {@code sequence2} will have been trimmed of their suffix when this
- * returns.
- */
- private static <E> List<E> trimSuffix(Comparison comparison, Iterable<E> ignoredElements,
- List<E> sequence1, List<E> sequence2) {
- final IEqualityHelper equalityHelper = comparison.getEqualityHelper();
- final int size1 = sequence1.size();
- final int size2 = sequence2.size();
-
- final List<E> suffix = Lists.newArrayList();
- int end1 = size1;
- int end2 = size2;
- boolean matching = true;
- while (end1 > 0 && end2 > 0 && matching) {
- final E first = sequence1.get(end1 - 1);
- final E second = sequence2.get(end2 - 1);
- if (equalityHelper.matchingValues(first, second)) {
- suffix.add(first);
- end1--;
- end2--;
- } else {
- boolean ignore1 = contains(comparison, equalityHelper, ignoredElements, first);
- boolean ignore2 = contains(comparison, equalityHelper, ignoredElements, second);
- if (ignore1) {
- end1--;
- }
- if (ignore2) {
- end2--;
- }
- if (!ignore1 && !ignore2) {
- matching = false;
- }
- }
- }
- sequence1.subList(end1, size1).clear();
- sequence2.subList(end2, size2).clear();
-
- return Lists.reverse(suffix);
- }
-
- /**
- * Checks whether the given {@code sequence} contains the given {@code element} according to the semantics
- * of the given {@code equalityHelper}.
- *
- * @param comparison
- * This will be used in order to retrieve the Match for EObjects when comparing them.
- * @param equalityHelper
- * The {@link EqualityHelper} gives us the necessary semantics for Object matching.
- * @param sequence
- * The sequence which elements we need to compare with {@code element}.
- * @param element
- * The element we are seeking in {@code sequence}.
- * @param <E>
- * Type of the sequence content.
- * @return {@code true} if the given {@code sequence} contains an element matching {@code element},
- * {@code false} otherwise.
- * @see EqualityHelper#matchingValues(Comparison, Object, Object)
- */
- private static <E> boolean contains(Comparison comparison, IEqualityHelper equalityHelper,
- Iterable<E> sequence, E element) {
- final Iterator<E> iterator = sequence.iterator();
- while (iterator.hasNext()) {
- E candidate = iterator.next();
- if (equalityHelper.matchingValues(candidate, element)) {
- return true;
- }
- }
- return false;
+ return org.eclipse.emf.compare.internal.utils.DiffUtil.longestCommonSubsequence(comparison,
+ sequence1, sequence2);
}
/**
- * This is a classic, single-threaded implementation. We use shorts for the score matrix so as to limit
- * the memory cost (we know the max LCS length is not greater than Short#MAX_VALUE).
- *
- * @param comparison
- * This will be used in order to retrieve the Match for EObjects when comparing them.
- * @param ignoredElements
- * Specifies elements that should be excluded from the subsequences.
- * @param sequence1
- * First of the two sequences to consider.
- * @param sequence2
- * Second of the two sequences to consider.
- * @param <E>
- * Type of the sequences content.
- * @return The LCS of the two given sequences. Will never be the same instance as one of the input
- * sequences.
- */
- private static <E> List<E> shortLongestCommonSubsequence(Comparison comparison,
- Iterable<E> ignoredElements, List<E> sequence1, List<E> sequence2) {
- final IEqualityHelper equalityHelper = comparison.getEqualityHelper();
- final int size1 = sequence1.size();
- final int size2 = sequence2.size();
-
- final short[][] matrix = new short[size1 + 1][size2 + 1];
-
- // Compute the LCS matrix
- for (int i = 1; i <= size1; i++) {
- final E first = sequence1.get(i - 1);
- for (int j = 1; j <= size2; j++) {
- // assume array dereferencing and arithmetics faster than equals
- final short current = matrix[i - 1][j - 1];
- final short nextIfNoMatch = (short)Math.max(matrix[i - 1][j], matrix[i][j - 1]);
-
- if (nextIfNoMatch > current) {
- matrix[i][j] = nextIfNoMatch;
- } else {
- final E second = sequence2.get(j - 1);
- if (equalityHelper.matchingValues(first, second)
- && !contains(comparison, equalityHelper, ignoredElements, second)) {
- matrix[i][j] = (short)(1 + current);
- } else {
- matrix[i][j] = nextIfNoMatch;
- }
- }
- }
- }
-
- // Traceback the matrix to create the final LCS
- int current1 = size1;
- int current2 = size2;
- final List<E> result = Lists.newArrayList();
-
- while (current1 > 0 && current2 > 0) {
- final short currentLength = matrix[current1][current2];
- final short nextLeft = matrix[current1][current2 - 1];
- final short nextUp = matrix[current1 - 1][current2];
- if (currentLength > nextLeft && currentLength > nextUp) {
- result.add(sequence1.get(current1 - 1));
- current1--;
- current2--;
- } else if (nextLeft >= nextUp) {
- current2--;
- } else {
- current1--;
- }
- }
-
- return Lists.reverse(result);
- }
-
- /**
- * This is a classic, single-threaded implementation. We know the max LCS length is greater than
- * Short#MAX_VALUE... the score matrix will thus be int-typed, resulting in a huge memory cost.
- *
- * @param comparison
- * This will be used in order to retrieve the Match for EObjects when comparing them.
- * @param ignoredElements
- * Specifies elements that should be excluded from the subsequences.
- * @param sequence1
- * First of the two sequences to consider.
- * @param sequence2
- * Second of the two sequences to consider.
- * @param <E>
- * Type of the sequences content.
- * @return The LCS of the two given sequences. Will never be the same instance as one of the input
- * sequences.
- */
- private static <E> List<E> intLongestCommonSubsequence(Comparison comparison,
- Iterable<E> ignoredElements, List<E> sequence1, List<E> sequence2) {
- final IEqualityHelper equalityHelper = comparison.getEqualityHelper();
- final int size1 = sequence1.size();
- final int size2 = sequence2.size();
-
- final int[][] matrix = new int[size1 + 1][size2 + 1];
-
- // Compute the LCS matrix
- for (int i = 1; i <= size1; i++) {
- final E first = sequence1.get(i - 1);
- for (int j = 1; j <= size2; j++) {
- // assume array dereferencing and arithmetics faster than equals
- final int current = matrix[i - 1][j - 1];
- final int nextIfNoMatch = Math.max(matrix[i - 1][j], matrix[i][j - 1]);
-
- if (nextIfNoMatch > current) {
- matrix[i][j] = nextIfNoMatch;
- } else {
- final E second = sequence2.get(j - 1);
- if (equalityHelper.matchingValues(first, second)
- && !contains(comparison, equalityHelper, ignoredElements, second)) {
- matrix[i][j] = 1 + current;
- } else {
- matrix[i][j] = nextIfNoMatch;
- }
- }
- }
- }
-
- // Traceback the matrix to create the final LCS
- int current1 = size1;
- int current2 = size2;
- final List<E> result = Lists.newArrayList();
-
- while (current1 > 0 && current2 > 0) {
- final int currentLength = matrix[current1][current2];
- final int nextLeft = matrix[current1][current2 - 1];
- final int nextUp = matrix[current1 - 1][current2];
- if (currentLength > nextLeft && currentLength > nextUp) {
- result.add(sequence1.get(current1 - 1));
- current1--;
- current2--;
- } else if (nextLeft >= nextUp) {
- current2--;
- } else {
- current1--;
- }
- }
-
- return Lists.reverse(result);
- }
-
- /*
- * TODO perf : all "lookups" in source and target could be rewritten by using the lcs elements' matches.
- * This may or may not help, should be profiled.
- */
- /**
* This will try and determine the index at which a given element from the {@code source} list should be
* inserted in the {@code target} list. We expect {@code newElement} to be an element from the
* {@code source} or to have a Match that allows us to map it to one of the {@code source} list's
@@ -539,202 +169,8 @@ public final class DiffUtil {
*/
public static <E> int findInsertionIndex(Comparison comparison, Iterable<E> ignoredElements,
List<E> source, List<E> target, E newElement) {
- final IEqualityHelper equalityHelper = comparison.getEqualityHelper();
-
- // We assume that "newElement" is in source but not in the target yet
- final List<E> lcs;
- if (ignoredElements != null) {
- lcs = longestCommonSubsequence(comparison, ignoredElements, source, target);
- } else {
- lcs = longestCommonSubsequence(comparison, source, target);
- }
-
- E firstLCS = null;
- E lastLCS = null;
- if (lcs.size() > 0) {
- firstLCS = lcs.get(0);
- lastLCS = lcs.listIterator(lcs.size()).previous();
- }
-
- final int noLCS = -2;
- int currentIndex = -1;
- int firstLCSIndex = -1;
- int lastLCSIndex = -1;
- if (firstLCS == null) {
- // We have no LCS
- firstLCSIndex = noLCS;
- lastLCSIndex = noLCS;
- }
-
- ListIterator<E> sourceIterator = source.listIterator();
- for (int i = 0; sourceIterator.hasNext() && (currentIndex == -1 || firstLCSIndex == -1); i++) {
- final E sourceElement = sourceIterator.next();
- if (currentIndex == -1 && equalityHelper.matchingValues(sourceElement, newElement)) {
- currentIndex = i;
- }
- if (firstLCSIndex == -1 && equalityHelper.matchingValues(sourceElement, firstLCS)) {
- firstLCSIndex = i;
- }
- }
- // The list may contain duplicates, use a reverse iteration to find the last from LCS.
- final int sourceSize = source.size();
- sourceIterator = source.listIterator(sourceSize);
- for (int i = sourceSize - 1; sourceIterator.hasPrevious() && lastLCSIndex == -1; i--) {
- final E sourceElement = sourceIterator.previous();
- if (lastLCSIndex == -1 && equalityHelper.matchingValues(sourceElement, lastLCS)) {
- lastLCSIndex = i;
- }
- }
-
- int insertionIndex = -1;
- if (firstLCSIndex == noLCS) {
- // We have no LCS. The two lists have no element in common. Insert at the very end of the target.
- insertionIndex = target.size();
- } else if (currentIndex < firstLCSIndex) {
- // The object we are to insert is before the LCS in source.
- insertionIndex = insertBeforeLCS(target, equalityHelper, firstLCS);
- } else if (currentIndex > lastLCSIndex) {
- // The object we are to insert is after the LCS in source.
- insertionIndex = findInsertionIndexAfterLCS(target, equalityHelper, lastLCS);
- } else {
- // Our object is in-between two elements A and B of the LCS in source
- insertionIndex = findInsertionIndexWithinLCS(source, target, equalityHelper, lcs, currentIndex);
- }
-
- // We somehow failed to determine the insertion index. Insert at the very end.
- if (insertionIndex == -1) {
- insertionIndex = target.size();
- }
-
- return insertionIndex;
- }
-
- /**
- * This will be called to try and find the insertion index for an element that is located in-between two
- * elements of the LCS between {@code source} and {@code target}.
- *
- * @param source
- * The List from which one element has to be added to the {@code target} list.
- * @param target
- * The List into which one element from {@code source} has to be added.
- * @param equalityHelper
- * The equality helper to use for this computation.
- * @param lcs
- * The lcs between {@code source} and {@code target}.
- * @param currentIndex
- * Current index (in {@code source} of the element we are to insert into {@code target}.
- * @param <E>
- * Type of the sequences content.
- * @return The index in the target list in which should be inserted that element.
- */
- private static <E> int findInsertionIndexWithinLCS(List<E> source, List<E> target,
- final IEqualityHelper equalityHelper, final List<E> lcs, int currentIndex) {
- int insertionIndex = -1;
- /*
- * If any element of the subsequence {<index of A>, <index of B>} from source had been in the same
- * subsequence in target, it would have been part of the LCS. We thus know none is.
- */
- // The insertion index will be just after A in target
-
- // First, find which element of the LCS is "A"
- int lcsIndexOfSubsequenceStart = -1;
- for (int i = 0; i < currentIndex; i++) {
- final E sourceElement = source.get(i);
-
- boolean isInLCS = false;
- for (int j = lcsIndexOfSubsequenceStart + 1; j < lcs.size() && !isInLCS; j++) {
- final E lcsElement = lcs.get(j);
-
- if (equalityHelper.matchingValues(sourceElement, lcsElement)) {
- isInLCS = true;
- lcsIndexOfSubsequenceStart++;
- }
- }
- }
-
- // Do we have duplicates before A in the lcs?
- final Multiset<E> dupesLCS = HashMultiset.create(lcs.subList(0, lcsIndexOfSubsequenceStart + 1));
- final E subsequenceStart = lcs.get(lcsIndexOfSubsequenceStart);
- int duplicatesToGo = dupesLCS.count(subsequenceStart) - 1;
-
- // Then, find the index of "A" in target
- for (int i = 0; i < target.size() && insertionIndex == -1; i++) {
- final E targetElement = target.get(i);
-
- if (equalityHelper.matchingValues(targetElement, subsequenceStart)) {
- if (duplicatesToGo > 0) {
- duplicatesToGo--;
- } else {
- insertionIndex = i + 1;
- }
- }
- }
-
- return insertionIndex;
- }
-
- /**
- * This will be called when we are to insert an element after the LCS in the {@code target} list.
- *
- * @param target
- * The List into which one element has to be added.
- * @param equalityHelper
- * The equality helper to use for this computation.
- * @param lastLCS
- * The last element of the LCS.
- * @param <E>
- * Type of the sequences content.
- * @return The index to use for insertion into {@code target} in order to add an element just after the
- * LCS.
- */
- private static <E> int findInsertionIndexAfterLCS(List<E> target, IEqualityHelper equalityHelper,
- E lastLCS) {
- int insertionIndex = -1;
- // The insertion index will be inside the subsequence {<LCS end>, <list.size()>} in target.
- /*
- * We'll insert it just after the LCS end : there cannot be any common element between the two lists
- * "after" the LCS since it would be part of the LCS itself.
- */
- for (int i = target.size() - 1; i >= 0 && insertionIndex == -1; i--) {
- final E targetElement = target.get(i);
- if (equalityHelper.matchingValues(targetElement, lastLCS)) {
- // We've reached the last element of the LCS in target. insert after it.
- insertionIndex = i + 1;
- }
- }
- return insertionIndex;
- }
-
- /**
- * This will be called when we are to insert an element before the LCS in the {@code target} list.
- *
- * @param target
- * The List into which one element has to be added.
- * @param equalityHelper
- * The equality helper to use for this computation.
- * @param firstLCS
- * The first element of the LCS.
- * @param <E>
- * Type of the sequences content.
- * @return The index to use for insertion into {@code target} in order to add an element just before the
- * LCS.
- */
- private static <E> int insertBeforeLCS(List<E> target, IEqualityHelper equalityHelper, E firstLCS) {
- int insertionIndex = -1;
- // The insertion index will be inside the subsequence {0, <LCS start>} in target
- /*
- * We'll insert it just before the LCS start : there cannot be any common element between the two
- * lists "before" the LCS since it would be part of the LCS itself.
- */
- for (int i = 0; i < target.size() && insertionIndex == -1; i++) {
- final E targetElement = target.get(i);
-
- if (equalityHelper.matchingValues(targetElement, firstLCS)) {
- // We've reached the first element from the LCS in target. Insert here
- insertionIndex = i;
- }
- }
- return insertionIndex;
+ return org.eclipse.emf.compare.internal.utils.DiffUtil.findInsertionIndex(comparison,
+ ignoredElements, source, target, newElement);
}
/**
@@ -779,7 +215,8 @@ public final class DiffUtil {
*/
public static <E> int findInsertionIndex(Comparison comparison, List<E> source, List<E> target,
E newElement) {
- return findInsertionIndex(comparison, null, source, target, newElement);
+ return org.eclipse.emf.compare.internal.utils.DiffUtil.findInsertionIndex(comparison, source, target,
+ newElement);
}
/**
@@ -799,194 +236,22 @@ public final class DiffUtil {
* inferred from {@code rightToLeft}.
* @see #findInsertionIndex(Comparison, Iterable, List, List, Object)
*/
- @SuppressWarnings("unchecked")
public static int findInsertionIndex(Comparison comparison, Diff diff, boolean rightToLeft) {
- final EStructuralFeature feature;
- final Object value;
- if (diff instanceof AttributeChange) {
- feature = ((AttributeChange)diff).getAttribute();
- value = ((AttributeChange)diff).getValue();
- } else if (diff instanceof ReferenceChange) {
- feature = ((ReferenceChange)diff).getReference();
- value = ((ReferenceChange)diff).getValue();
- } else {
- throw new IllegalArgumentException(EMFCompareMessages.getString(
- "DiffUtil.IllegalDiff", diff.eClass().getName())); //$NON-NLS-1$
- }
- if (!feature.isMany()) {
- throw new IllegalArgumentException(EMFCompareMessages.getString(
- "DiffUtil.IllegalFeature", feature.getName())); //$NON-NLS-1$
- }
- final Match match = diff.getMatch();
-
- final EObject expectedContainer;
- if (feature instanceof EReference && ((EReference)feature).isContainment()
- && diff.getKind() == DifferenceKind.MOVE) {
- // The value can only be an EObject, and its match cannot be null.
- // If any of these two assumptions is wrong, something went horribly awry beforehand.
- final Match valueMatch = comparison.getMatch((EObject)value);
-
- final Match targetContainerMatch;
- // If it exists, use the source side's container as reference
- if (rightToLeft && valueMatch.getRight() != null) {
- targetContainerMatch = comparison.getMatch(valueMatch.getRight().eContainer());
- } else if (!rightToLeft && valueMatch.getLeft() != null) {
- targetContainerMatch = comparison.getMatch(valueMatch.getLeft().eContainer());
- } else {
- // Otherwise, the value we're moving on one side has been removed from its source side.
- targetContainerMatch = comparison.getMatch(valueMatch.getOrigin().eContainer());
- }
- if (rightToLeft) {
- expectedContainer = targetContainerMatch.getLeft();
- } else {
- expectedContainer = targetContainerMatch.getRight();
- }
- } else if (rightToLeft) {
- expectedContainer = match.getLeft();
- } else {
- expectedContainer = match.getRight();
- }
-
- final List<Object> sourceList = getSourceList(diff, feature, rightToLeft);
- final List<Object> targetList;
-
- if (expectedContainer != null) {
- final List<Object> temp = (List<Object>)ReferenceUtil.safeEGet(expectedContainer, feature);
- if (feature == EcorePackage.Literals.ECLASS__ESUPER_TYPES
- || feature == EcorePackage.Literals.EOPERATION__EEXCEPTIONS) {
- // workaround 394286
- targetList = temp;
- } else if (temp instanceof InternalEList<?>) {
- // EMF ignores the "resolve" flag for containment lists...
- targetList = ((InternalEList<Object>)temp).basicList();
- } else {
- targetList = temp;
- }
- } else {
- targetList = ImmutableList.of();
- }
-
- Iterable<Object> ignoredElements = Iterables.concat(computeIgnoredElements(targetList, diff),
- Collections.singleton(value));
- // We know we'll have to iterate quite a number of times on this one.
- ignoredElements = Lists.newArrayList(ignoredElements);
-
- return DiffUtil.findInsertionIndex(comparison, ignoredElements, sourceList, targetList, value);
- }
-
- /**
- * Retrieves the "source" list of the given {@code diff}. This will be different according to the kind of
- * change and the direction of the merging.
- *
- * @param diff
- * The diff for which merging we need a 'source'.
- * @param feature
- * The feature on which the merging is actually taking place.
- * @param rightToLeft
- * Direction of the merging. {@code true} if the merge is to be done on the left side, making
- * 'source' the right side, {@code false} otherwise.
- * @return The list that should be used as a source for this merge. May be empty, but never
- * <code>null</code>.
- */
- @SuppressWarnings("unchecked")
- private static List<Object> getSourceList(Diff diff, EStructuralFeature feature, boolean rightToLeft) {
- final Match match = diff.getMatch();
- final List<Object> sourceList;
- final EObject expectedContainer;
-
- if (diff.getKind() == DifferenceKind.MOVE) {
- final boolean undoingLeft = rightToLeft && diff.getSource() == DifferenceSource.LEFT;
- final boolean undoingRight = !rightToLeft && diff.getSource() == DifferenceSource.RIGHT;
-
- if ((undoingLeft || undoingRight) && match.getOrigin() != null) {
- expectedContainer = match.getOrigin();
- } else if (rightToLeft) {
- expectedContainer = match.getRight();
- } else {
- expectedContainer = match.getLeft();
- }
-
- } else {
- if (match.getOrigin() != null && diff.getKind() == DifferenceKind.DELETE) {
- expectedContainer = match.getOrigin();
- } else if (rightToLeft) {
- expectedContainer = match.getRight();
- } else {
- expectedContainer = match.getLeft();
- }
- }
-
- if (expectedContainer != null) {
- final List<Object> temp = (List<Object>)ReferenceUtil.safeEGet(expectedContainer, feature);
- if (feature == EcorePackage.Literals.ECLASS__ESUPER_TYPES
- || feature == EcorePackage.Literals.EOPERATION__EEXCEPTIONS) {
- // workaround 394286
- sourceList = temp;
- } else if (temp instanceof InternalEList<?>) {
- // EMF ignores the "resolve" flag for containment lists...
- sourceList = ((InternalEList<Object>)temp).basicList();
- } else {
- sourceList = temp;
- }
- } else {
- sourceList = ImmutableList.of();
- }
-
- return sourceList;
- }
-
- /**
- * When computing the insertion index of an element in a list, we need to ignore all elements present in
- * that list that feature unresolved Diffs on the same feature.
- *
- * @param candidates
- * The sequence in which we need to compute an insertion index.
- * @param diff
- * The diff we are computing an insertion index for.
- * @param <E>
- * Type of the list's content.
- * @return The list of elements that should be ignored when computing the insertion index for a new
- * element in {@code candidates}.
- */
- private static <E> Iterable<E> computeIgnoredElements(Iterable<E> candidates, final Diff diff) {
- final Match match = diff.getMatch();
- final Iterable<? extends Diff> filteredCandidates = Lists.newArrayList(match.getDifferences());
- final EStructuralFeature feature;
- if (diff instanceof AttributeChange) {
- feature = ((AttributeChange)diff).getAttribute();
- } else if (diff instanceof ReferenceChange) {
- feature = ((ReferenceChange)diff).getReference();
- } else {
- return Collections.emptyList();
- }
-
- final Set<E> ignored = Sets.newLinkedHashSet();
- for (E candidate : candidates) {
- if (candidate instanceof EObject) {
- final Iterable<? extends Diff> differences = match.getComparison().getDifferences(
- (EObject)candidate);
- if (Iterables.any(differences, new UnresolvedDiffMatching(feature, candidate))) {
- ignored.add(candidate);
- }
- } else {
- if (Iterables.any(filteredCandidates, new UnresolvedDiffMatching(feature, candidate))) {
- ignored.add(candidate);
- }
- }
- }
- return ignored;
+ return org.eclipse.emf.compare.internal.utils.DiffUtil.findInsertionIndex(comparison, diff,
+ rightToLeft);
}
/**
* When merging a {@link Diff}, returns the sub diffs of this given diff, and all associated diffs (see
* {@link DiffUtil#getAssociatedDiffs(Iterable, boolean, Diff)}) of these sub diffs.
* <p>
- * If the diff is an {@link AttributeChange} or a @{code ResourceAttachmentChange}, this method will
- * return an empty iterable.
+ * If the diff is an {@link org.eclipse.emf.compare.AttributeChange} or a @{code
+ * ResourceAttachmentChange}, this method will return an empty iterable.
* </p>
* <p>
- * If the diff is a {@link ReferenceChange} this method will return all differences contained in the match
- * that contains the value of the reference change, and all associated diffs of these differences.
+ * If the diff is a {@link org.eclipse.emf.compare.ReferenceChange} this method will return all
+ * differences contained in the match that contains the value of the reference change, and all associated
+ * diffs of these differences.
* </p>
*
* @param leftToRight
@@ -996,112 +261,7 @@ public final class DiffUtil {
* @since 3.0
*/
public static Function<Diff, Iterable<Diff>> getSubDiffs(final boolean leftToRight) {
- return getSubDiffs(leftToRight, new LinkedHashSet<Diff>());
- }
-
- /**
- * When merging a {@link Diff}, returns the sub diffs of this given diff, and all associated diffs (see
- * {@link DiffUtil#getAssociatedDiffs(Iterable, boolean, Diff)}) of these sub diffs.
- * <p>
- * If the diff is an {@link AttributeChange} or a @{code ResourceAttachmentChange}, this method will
- * return an empty iterable.
- * </p>
- * <p>
- * If the diff is a {@link ReferenceChange} this method will return all differences contained in the match
- * that contains the value of the reference change, and all associated diffs of these differences.
- * </p>
- *
- * @param leftToRight
- * the direction of merge.
- * @param processedDiffs
- * a set of diffs which have been already processed.
- * @return an iterable containing the sub diffs of this given diff, and all associated diffs of these sub
- * diffs.
- * @since 3.0
- */
- private static Function<Diff, Iterable<Diff>> getSubDiffs(final boolean leftToRight,
- final LinkedHashSet<Diff> processedDiffs) {
- return new Function<Diff, Iterable<Diff>>() {
- public Iterable<Diff> apply(Diff diff) {
- if (diff instanceof ReferenceChange) {
- Match matchOfValue = diff.getMatch().getComparison().getMatch(
- ((ReferenceChange)diff).getValue());
- if (((ReferenceChange)diff).getReference().isContainment()) {
- final Iterable<Diff> subDiffs = matchOfValue.getAllDifferences();
- addAll(processedDiffs, subDiffs);
- final Iterable<Diff> associatedDiffs = getAssociatedDiffs(diff, subDiffs,
- processedDiffs, leftToRight);
- return ImmutableSet.copyOf(concat(subDiffs, associatedDiffs));
- }
- }
- return ImmutableSet.of();
- }
- };
- }
-
- /**
- * When merging a {@link Diff}, returns the associated diffs of the sub diffs of the diff, and all sub
- * diffs (see {@link DiffUtil#getSubDiffs(boolean)}) of these associated diffs.
- * <p>
- * The associated diffs of a diff are :
- * <p>
- * - {@link Diff#getRequiredBy()} if the source of the diff is the left side and the direction of the
- * merge is right to left.
- * </p>
- * <p>
- * - {@link Diff#getRequiredBy()} if the source of the diff is the right side and the direction of the
- * merge is left to right.
- * </p>
- * <p>
- * - {@link Diff#getRequires()} if the source of the diff is the left side and the direction of the merge
- * is left to right.
- * </p>
- * <p>
- * - {@link Diff#getRequires()} if the source of the diff is the right side and the direction of the merge
- * is right to left.
- * </p>
- * </p>
- *
- * @param diffRoot
- * the given diff.
- * @param subDiffs
- * the iterable of sub diffs for which we want the associated diffs.
- * @param processedDiffs
- * a set of diffs which have been already processed.
- * @param leftToRight
- * the direction of merge.
- * @return an iterable containing the associated diffs of these given sub diffs, and all sub diffs of
- * these associated diffs.
- * @since 3.0
- */
- private static Iterable<Diff> getAssociatedDiffs(final Diff diffRoot, Iterable<Diff> subDiffs,
- LinkedHashSet<Diff> processedDiffs, boolean leftToRight) {
- Collection<Diff> associatedDiffs = new HashSet<Diff>();
- for (Diff diff : subDiffs) {
- final Collection<Diff> reqs = new LinkedHashSet<Diff>();
- if (leftToRight) {
- if (diff.getSource() == DifferenceSource.LEFT) {
- reqs.addAll(diff.getRequires());
- } else {
- reqs.addAll(diff.getRequiredBy());
- }
- } else {
- if (diff.getSource() == DifferenceSource.LEFT) {
- reqs.addAll(diff.getRequiredBy());
- } else {
- reqs.addAll(diff.getRequires());
- }
- }
- reqs.remove(diffRoot);
- associatedDiffs.addAll(reqs);
- for (Diff req : reqs) {
- if (!Iterables.contains(subDiffs, req) && !processedDiffs.contains(req)) {
- processedDiffs.add(req);
- addAll(associatedDiffs, getSubDiffs(leftToRight, processedDiffs).apply(req));
- }
- }
- }
- return associatedDiffs;
+ return ComparisonUtil.getSubDiffs(leftToRight);
}
/**
@@ -1142,91 +302,4 @@ public final class DiffUtil {
boolean leftToRight) {
return Collections.emptyList();
}
-
- /**
- * This can be used to check whether a given Diff affects a value for which we can find another,
- * unresolved Diff on a given Feature.
- *
- * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
- */
- private static class UnresolvedDiffMatching implements Predicate<Diff> {
- /** Feature on which we expect an unresolved diff. */
- private final EStructuralFeature feature;
-
- /** Element for which we expect an unresolved diff. */
- private final Object element;
-
- /**
- * Constructs a predicate that can be used to retrieve all unresolved diffs that apply to the given
- * {@code feature} and {@code element}.
- *
- * @param feature
- * The feature which our diffs must concern.
- * @param element
- * The element which must be our diffs' target.
- */
- public UnresolvedDiffMatching(EStructuralFeature feature, Object element) {
- this.feature = feature;
- this.element = element;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see com.google.common.base.Predicate#apply(java.lang.Object)
- */
- public boolean apply(Diff input) {
- boolean apply = false;
- if (input instanceof AttributeChange) {
- apply = input.getState() == DifferenceState.UNRESOLVED
- && ((AttributeChange)input).getAttribute() == feature
- && matchingValues((AttributeChange)input, element);
- } else if (input instanceof ReferenceChange) {
- apply = input.getState() == DifferenceState.UNRESOLVED
- && ((ReferenceChange)input).getReference() == feature
- && matchingValues((ReferenceChange)input, element);
- } else {
- apply = false;
- }
- return apply;
- }
-
- /**
- * Checks that the value of the given diff matches <code>value</code>, resorting to the equality
- * helper if needed.
- *
- * @param diff
- * The diff which value we need to check.
- * @param value
- * The expected value of <code>diff</code>
- * @return <code>true</code> if the value matches.
- */
- private boolean matchingValues(AttributeChange diff, Object value) {
- if (diff.getValue() == value) {
- return true;
- }
- // Only resort to the equality helper as "last resort"
- final IEqualityHelper helper = diff.getMatch().getComparison().getEqualityHelper();
- return helper.matchingAttributeValues(diff.getValue(), value);
- }
-
- /**
- * Checks that the value of the given diff matches <code>value</code>, resorting to the equality
- * helper if needed.
- *
- * @param diff
- * The diff which value we need to check.
- * @param value
- * The expected value of <code>diff</code>
- * @return <code>true</code> if the value matches.
- */
- private boolean matchingValues(ReferenceChange diff, Object value) {
- if (diff.getValue() == value) {
- return true;
- }
- // Only resort to the equality helper as "last resort"
- final IEqualityHelper helper = diff.getMatch().getComparison().getEqualityHelper();
- return helper.matchingValues(diff.getValue(), value);
- }
- }
}

Back to the top