Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Fleck2017-01-20 04:36:09 -0500
committerLaurent Goubet2017-06-27 11:14:34 -0400
commitb6d0be4ef8056a11690e2d0ce514476befcf2f1b (patch)
tree8bd4ff680a14e694649e0f5b7bbafdc16b0d806f
parent8bc41b3003625c3b09dc171f0ab383929ce04d72 (diff)
downloadorg.eclipse.emf.compare-b6d0be4ef8056a11690e2d0ce514476befcf2f1b.tar.gz
org.eclipse.emf.compare-b6d0be4ef8056a11690e2d0ce514476befcf2f1b.tar.xz
org.eclipse.emf.compare-b6d0be4ef8056a11690e2d0ce514476befcf2f1b.zip
[487151] Accept all non-conflicting changes fails to merge some diffs
Adapt diff merge computer to only return diffs that actually lead to a conflict in the exception and not all connected diffs to ensure that non-conflicting diffs are merged. Includes tests. Bug: 487151 Change-Id: I3f08e09c3e67066c57d86f572dc66a2d09ca5bb2 Signed-off-by: Martin Fleck <mfleck@eclipsesource.com> Signed-off-by: Simon Delisle <simon.delisle@ericsson.com> Also-by: Simon Delisle <simon.delisle@ericsson.com>
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/META-INF/MANIFEST.MF3
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/MergeNonConflictingCascadingFilterTest.java527
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/left/left.di2
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/left/left.notation21
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/left/left.uml4
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/origin/ancestor.di2
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/origin/ancestor.notation44
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/origin/ancestor.uml6
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/right/right.di2
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/right/right.notation89
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/right/right.uml9
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/ecore/left/left.ecore3
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/ecore/origin/ancestor.ecore5
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/ecore/right/right.ecore21
-rw-r--r--plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/suite/AllTests.java7
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/ConflictDetectionTest.java16
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/ConflictInputData.java12
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/e3/conflict_e3_left.nodes7
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/e3/conflict_e3_origin.nodes11
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/e3/conflict_e3_right.nodes5
-rw-r--r--plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/useCases1
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ComputeDiffsToMerge.java23
22 files changed, 806 insertions, 14 deletions
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/META-INF/MANIFEST.MF
index 324be0697..f0aafa4cc 100644
--- a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/META-INF/MANIFEST.MF
@@ -38,7 +38,8 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.emf.compare.rcp.ui.tests,
org.eclipse.emf.compare.ide.ui.tests;bundle-version="4.0.0",
org.eclipse.emf.compare.uml2.rcp.ui.tests;bundle-version="2.2.0",
- org.eclipse.emf.compare.uml2.ide.tests
+ org.eclipse.emf.compare.uml2.ide.tests,
+ org.eclipse.emf.compare.ide.ui.tests.framework
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-Vendor: %providerName
Import-Package: com.google.common.base;version="[15.0.0,22.0.0)",
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/MergeNonConflictingCascadingFilterTest.java b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/MergeNonConflictingCascadingFilterTest.java
new file mode 100644
index 000000000..7b511fe99
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/MergeNonConflictingCascadingFilterTest.java
@@ -0,0 +1,527 @@
+/*******************************************************************************
+ * Copyright (c) 2017 EclipseSource Services GmbH and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Martin Fleck - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.diagram.papyrus.tests.structuremergeviewer.actions;
+
+import static com.google.common.collect.Iterables.all;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Iterables.size;
+import static org.eclipse.emf.compare.DifferenceState.MERGED;
+import static org.eclipse.emf.compare.DifferenceState.UNRESOLVED;
+import static org.eclipse.emf.compare.merge.AbstractMerger.SUB_DIFF_AWARE_OPTION;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.containsConflictOfTypes;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasState;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.Conflict;
+import org.eclipse.emf.compare.ConflictKind;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.DifferenceState;
+import org.eclipse.emf.compare.MatchResource;
+import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeNonConflictingRunnable;
+import org.eclipse.emf.compare.ide.ui.tests.framework.RuntimeTestRunner;
+import org.eclipse.emf.compare.ide.ui.tests.framework.annotations.Compare;
+import org.eclipse.emf.compare.ide.ui.tests.framework.internal.CompareTestSupport;
+import org.eclipse.emf.compare.internal.merge.MergeMode;
+import org.eclipse.emf.compare.merge.IMergeOptionAware;
+import org.eclipse.emf.compare.merge.IMerger.Registry;
+import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Model;
+import org.eclipse.uml2.uml.Package;
+import org.eclipse.uml2.uml.PackageableElement;
+import org.junit.runner.RunWith;
+
+/**
+ * <p>
+ * This class tests the expected behavior of accepting non-conflicting changes when the cascading differences
+ * filter is enabled. The cascading differences filter handles the setting of sub-diff awareness in mergers.
+ * </p>
+ * <p>
+ * In particular, we test that bug 487151 is fixed where conflicting diffs are merged when 'accepting
+ * non-conflicting changes'. The source of this bug lies in the sub-diff awareness of mergers that merge
+ * sub-diffs, their dependendies, their sub-diffs, etc. Therefore, this bug only occurs when sub-diff
+ * awareness ('cascading differences filter' to the user) is enabled.
+ * </p>
+ * We use the following structure to test the correct behavior:
+ * <ul>
+ * <li>Origin: Package 'Package1' containing class 'Class1'</li>
+ * <li>Left: Package 'Package1' (class 'Class1' removed)</li>
+ * <li>Right: Package 'Package1' containing class 'Class1', and class 'Class2' subclassing class 'Class1'
+ * (class 'Class2' and generalization added)
+ * </ul>
+ * For EMF Compare this means that we have the following relationships between the UML differences:
+ * <ul>
+ * <li>L1: Left DELETE Class 1 (conflicts with R4)</li>
+ * <li>R1: Right ADD Class 2 (subDiffs because also related to Class 2: R2 and R3)</li>
+ * <li>R2: Right ADD Generalization (refinedBy R3 and R4)</li>
+ * <li>R3: Right ADD generalization to Class2.generalization</li>
+ * <li>R4: Right CHANGE generalization.general to Class 1 (conflicts with L1)</li>
+ * </ul>
+ * <p>
+ * In the comparison, we detect a conflict between adding the generalization, setting the 'general' of the
+ * generalization and the deletion of class 'Class1'. When accepting all non-conflicting changes (left changes
+ * accepted, right changes merged into left for non-conflicts), we expect the left model to add nothing when
+ * sub-diffs are enabled and to add Class 2 (R1) when sub-diffs are not enabled. The generalization (R2-R4)
+ * should not be added in any case since in UML we consider the addition of the generalization and the setting
+ * of the 'general' as a whole (DirectedRelationshipChange) and the 'general' can not be set since 'Class2'
+ * has been removed (conflict).
+ * </p>
+ * <p>
+ * All non-conflicting diffs should be in state {@link DifferenceState#MERGED} and all conflicting diffs
+ * should be in state {@link DifferenceState#UNRESOLVED}.
+ * </p>
+ *
+ * @author Martin Fleck <mfleck@eclipsesource.com>
+ * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=487151
+ */
+@SuppressWarnings({"restriction", "nls", "boxing" })
+@RunWith(RuntimeTestRunner.class)
+public class MergeNonConflictingCascadingFilterTest {
+ /** Cached cascading options before the last time the filter was enabled or disabled. */
+ private static final Map<IMergeOptionAware, Object> CACHED_OPTIONS = Maps.newHashMap();
+
+ private static Registry MERGER_REGISTRY = EMFCompareRCPPlugin.getDefault().getMergerRegistry();
+
+ /** Filter On setting **/
+ private static boolean FILTER_ON = true;
+
+ /** Filter Off setting **/
+ private static boolean FILTER_OFF = false;
+
+ /**
+ * <p>
+ * Tests that bug 487151 is fixed when the cascading differences filter is turned ON and graphical
+ * elements and their relationships are involved.
+ * </p>
+ */
+ @Compare(left = "data/bug487151/classes/left/left.notation", right = "data/bug487151/classes/right/right.notation", ancestor = "data/bug487151/classes/origin/ancestor.notation")
+ public void testBug487151_Papyrus_On(final Comparison comparison) {
+ // lots of graphical diffs, details not important
+ Integer nrDiffs = null;
+
+ // 1 REAL structural and 1 REAL graphical
+ int nrRealConflicts = 2;
+
+ // graphical diffs are not conflicting
+ boolean hasNonConflictingDiffs = true;
+
+ // conflicting structural differences: LEFT delete Class1, RIGHT change Generalization.general, RIGHT
+ // add DirectedRelationshipChange + graphical differences: ...
+ boolean hasConflictingDiffs = true;
+
+ assertUMLDiffsAndStructure(comparison, FILTER_ON, nrDiffs, nrRealConflicts, hasNonConflictingDiffs,
+ hasConflictingDiffs);
+ }
+
+ /**
+ * <p>
+ * Tests that bug 487151 is fixed when the cascading differences filter is turned OFF and graphical
+ * elements and their relationships are involved.
+ * </p>
+ */
+ @Compare(left = "data/bug487151/classes/left/left.notation", right = "data/bug487151/classes/right/right.notation", ancestor = "data/bug487151/classes/origin/ancestor.notation")
+ public void testBug487151_Papyrus_Off(final Comparison comparison) {
+ // lots of graphical diffs, details not important
+ Integer nrDiffs = null;
+
+ // 1 REAL structural and 1 REAL graphical
+ int nrRealConflicts = 2;
+
+ // graphical diffs are not conflicting
+ boolean hasNonConflictingDiffs = true;
+
+ // conflicting structural differences: LEFT delete Class1, RIGHT change Generalization.general, RIGHT
+ // add DirectedRelationshipChange + graphical differences: ...
+ boolean hasConflictingDiffs = true;
+
+ assertUMLDiffsAndStructure(comparison, FILTER_OFF, nrDiffs, nrRealConflicts, hasNonConflictingDiffs,
+ hasConflictingDiffs);
+ }
+
+ /**
+ * <p>
+ * Tests that bug 487151 is fixed when the cascading differences filter is turned ON and only UML elements
+ * and their relationships are involved.
+ * </p>
+ */
+ @Compare(left = "data/bug487151/classes/left/left.uml", right = "data/bug487151/classes/right/right.uml", ancestor = "data/bug487151/classes/origin/ancestor.uml")
+ public void testBug487151_UML_On(final Comparison comparison) {
+ // 5 differences: LEFT delete Class1, RIGHT add Class2, RIGHT add generalization, RIGHT change
+ // Generalization.general, RIGHT add DirectedRelationshipChange (refining add/change for
+ // Generalization; from UML PostProcessor)
+ int nrDiffs = 5;
+
+ // 1 REAL structural conflict
+ int nrRealConflicts = 1;
+
+ // all diffs are in conflict through their relationships
+ boolean hasNonConflictingDiffs = false;
+ boolean hasConflictingDiffs = true;
+
+ assertUMLDiffsAndStructure(comparison, FILTER_ON, nrDiffs, nrRealConflicts, hasNonConflictingDiffs,
+ hasConflictingDiffs);
+ }
+
+ /**
+ * <p>
+ * Tests that bug 487151 is fixed when the cascading differences filter is turned OFF and only UML
+ * elements and their relationships are involved.
+ * </p>
+ */
+ @Compare(left = "data/bug487151/classes/left/left.uml", right = "data/bug487151/classes/right/right.uml", ancestor = "data/bug487151/classes/origin/ancestor.uml")
+ public void testBug487151_UML_Off(final Comparison comparison) {
+ // 5 differences: LEFT delete Class1, RIGHT add Class2, RIGHT add generalization, RIGHT change
+ // Generalization.general, RIGHT add DirectedRelationshipChange (refining add/change for
+ // Generalization; from UML PostProcessor)
+ int nrDiffs = 5;
+
+ // 1 REAL structural conflict
+ int nrRealConflicts = 1;
+
+ // all diffs are in conflict through their relationships
+ boolean hasNonConflictingDiffs = true;
+ boolean hasConflictingDiffs = true;
+
+ assertUMLDiffsAndStructure(comparison, FILTER_OFF, nrDiffs, nrRealConflicts, hasNonConflictingDiffs,
+ hasConflictingDiffs);
+ }
+
+ /**
+ * <p>
+ * Tests that bug 487151 is fixed when the cascading differences filter is turned ON and and Ecore
+ * representation is used. Since we do not use refinement in Ecore and the Generalization is represented
+ * as a reference, Class 2 can be added independently of the filter setting.
+ * </p>
+ * <ul>
+ * <li>Origin: Package 'Package1' containing class 'Class1'</li>
+ * <li>Left: Package 'Package1' (class 'Class1' removed)</li>
+ * <li>Right: Package 'Package1' containing class 'Class1' and class 'Class2' with reference named
+ * 'Generalization' that has as eType 'Class1' (class 'Class2' and added generalization reference)
+ * </ul>
+ * <p>
+ * In the comparison, we detect a conflict between setting the eType of the 'Generalization' reference and
+ * the deletion of class 'Class1'. When accepting all non-conflicting changes (left changes accepted,
+ * right changes merged into left for non-conflicts), we expect the left model to have 'Class2' AND the
+ * 'Generalization' reference without an eType since 'Class1' has been deleted. All non-conflicting diffs
+ * should be in state {@link DifferenceState#MERGED} and all conflicting diffs should be in state
+ * {@link DifferenceState#UNRESOLVED}.
+ * </p>
+ */
+ @Compare(left = "data/bug487151/ecore/left/left.ecore", right = "data/bug487151/ecore/right/right.ecore", ancestor = "data/bug487151/ecore/origin/ancestor.ecore")
+ public void testBug487151_Ecore_On(final Comparison comparison, final CompareTestSupport support) {
+ // 4 differences: LEFT delete Class1, RIGHT add Class2, RIGHT add generalization, RIGHT change
+ // Generalization.general
+ int nrDiffs = 4;
+
+ // 1 conflict (REAL)
+ int nrRealConflicts = 1;
+
+ // non-conflicting difference: RIGHT add Class2
+ boolean hasNonConflictingDiffs = true;
+
+ // conflicting differences: LEFT delete Class1, RIGHT change Generalization.eType, RIGHT add
+ // DirectedRelationshipChange
+ boolean hasConflictingDiffs = true;
+
+ assertEcoreDiffsAndStructure(comparison, support, FILTER_ON, nrDiffs, nrRealConflicts,
+ hasNonConflictingDiffs, hasConflictingDiffs);
+ }
+
+ /**
+ * <p>
+ * Tests that bug 487151 is fixed when the cascading differences filter is turned ON and and Ecore
+ * representation is used. Since we do not use refinement in Ecore and the Generalization is represented
+ * as a reference, Class 2 can be added independently of the filter setting.
+ * </p>
+ * <ul>
+ * <li>Origin: Package 'Package1' containing class 'Class1'</li>
+ * <li>Left: Package 'Package1' (class 'Class1' removed)</li>
+ * <li>Right: Package 'Package1' containing class 'Class1' and class 'Class2' with reference named
+ * 'Generalization' that has as eType 'Class1' (class 'Class2' and added generalization reference)
+ * </ul>
+ * <p>
+ * In the comparison, we detect a conflict between setting the eType of the 'Generalization' reference and
+ * the deletion of class 'Class1'. When accepting all non-conflicting changes (left changes accepted,
+ * right changes merged into left for non-conflicts), we expect the left model to have 'Class2' AND the
+ * 'Generalization' reference without an eType since 'Class1' has been deleted. All non-conflicting diffs
+ * should be in state {@link DifferenceState#MERGED} and all conflicting diffs should be in state
+ * {@link DifferenceState#UNRESOLVED}.
+ * </p>
+ */
+ @Compare(left = "data/bug487151/ecore/left/left.ecore", right = "data/bug487151/ecore/right/right.ecore", ancestor = "data/bug487151/ecore/origin/ancestor.ecore")
+ public void testBug487151_Ecore_Off(final Comparison comparison, final CompareTestSupport support) {
+ // 4 differences: LEFT delete Class1, RIGHT add Class2, RIGHT add generalization, RIGHT change
+ // Generalization.general
+ int nrDiffs = 4;
+
+ // 1 conflict (REAL)
+ int nrRealConflicts = 1;
+
+ // non-conflicting difference: RIGHT add Class2
+ boolean hasNonConflictingDiffs = true;
+
+ // conflicting differences: LEFT delete Class1, RIGHT change Generalization.eType, RIGHT add
+ // DirectedRelationshipChange
+ boolean hasConflictingDiffs = true;
+
+ assertEcoreDiffsAndStructure(comparison, support, FILTER_OFF, nrDiffs, nrRealConflicts,
+ hasNonConflictingDiffs, hasConflictingDiffs);
+ }
+
+ /**
+ * Asserts the expected differences and structure for Ecore models. Specifically, that independently of
+ * the filter setting, the class 2 and its generalization is added, but the type of the generalization is
+ * not set.
+ *
+ * @param comparison
+ * comparison
+ * @param support
+ * test support for the comparison
+ * @param filter
+ * sub-diff filter setting
+ * @param nrDiffs
+ * expected number of differences
+ * @param nrRealConflicts
+ * expected number of real conflicts
+ * @param hasNonConflictingDiffs
+ * whether non-conflicting diffs are expected
+ * @param hasConflictingDiffs
+ * whether conflicting diffs are expected
+ */
+ protected void assertEcoreDiffsAndStructure(Comparison comparison, CompareTestSupport support,
+ boolean filter, int nrDiffs, int nrRealConflicts, boolean hasNonConflictingDiffs,
+ boolean hasConflictingDiffs) {
+ final List<Diff> differences = comparison.getDifferences();
+ final List<Conflict> conflicts = comparison.getConflicts();
+
+ // 4 differences: LEFT delete Class1, RIGHT add Class2, RIGHT add generalization, RIGHT change
+ // Generalization.general
+ assertEquals(nrDiffs, differences.size());
+
+ // real conflicts
+ Iterable<Conflict> realConflicts = filter(conflicts, containsConflictOfTypes(ConflictKind.REAL));
+ assertEquals(nrRealConflicts, size(realConflicts));
+
+ // before accepting any changes, all differences are unresolved
+ assertTrue(all(differences, hasState(UNRESOLVED)));
+
+ // accept non-conflicting changes and collect differences
+ Iterable<Diff> nonConflictingDifferences = acceptNonConflictingChanges(comparison, filter);
+ assertEquals(hasNonConflictingDiffs, !isEmpty(nonConflictingDifferences));
+
+ // conflicting differences: LEFT delete Class1, RIGHT change Generalization.eType, RIGHT add
+ // DirectedRelationshipChange
+ final List<Diff> conflictingDifferences = getConflictingDifferences(
+ Lists.newArrayList(nonConflictingDifferences), conflicts);
+ assertEquals(hasConflictingDiffs, !isEmpty(conflictingDifferences));
+
+ // all accepted differences have been merged
+ assertTrue(all(nonConflictingDifferences, hasState(MERGED)));
+
+ // any differences part of real conflicts are still unresolved
+ assertTrue(all(conflictingDifferences, hasState(UNRESOLVED)));
+
+ // assert new structure (right changes merged into left for non-conflicts)
+ EObject root = support.getLeftResource().getContents().get(0);
+ assertNotNull(root);
+ assertTrue(root instanceof EPackage);
+ EPackage package1 = (EPackage)root;
+ assertNotNull(package1);
+ EClassifier class1 = package1.getEClassifier("Class1");
+ assertNull(class1); // still null due to conflict
+ EClassifier class2 = package1.getEClassifier("Class2");
+
+ // regardless of filter, class 2 and generalization is added
+ assertNotNull(class2); // newly added
+ EClass class2class = (EClass)class2;
+ EStructuralFeature class2generalization = class2class.getEStructuralFeature("Generalization");
+ assertNotNull(class2generalization); // reference generalization has been added
+ assertNull(class2generalization.getEType()); // no type set due to conflict
+ }
+
+ /**
+ * Asserts the expected differences and structure for UML models. Specifically, whether Class 2
+ * conflicting with sub-diff filter enabled is added.
+ *
+ * @param comparison
+ * comparison
+ * @param filter
+ * sub-diff filter setting
+ * @param nrDiffs
+ * expected number of differences
+ * @param nrRealConflicts
+ * expected number of real conflicts
+ * @param hasNonConflictingDiffs
+ * whether non-conflicting diffs are expected
+ * @param hasConflictingDiffs
+ * whether conflicting diffs are expected
+ */
+ protected void assertUMLDiffsAndStructure(Comparison comparison, boolean filter, Integer nrDiffs,
+ int nrRealConflicts, boolean hasNonConflictingDiffs, boolean hasConflictingDiffs) {
+ final List<Diff> differences = comparison.getDifferences();
+ final List<Conflict> conflicts = comparison.getConflicts();
+
+ if (nrDiffs != null) {
+ assertEquals(nrDiffs.intValue(), differences.size());
+ }
+
+ Iterable<Conflict> realConflicts = filter(conflicts, containsConflictOfTypes(ConflictKind.REAL));
+ assertEquals(nrRealConflicts, size(realConflicts));
+
+ // before accepting any changes, all differences are unresolved
+ assertTrue(all(differences, hasState(UNRESOLVED)));
+
+ // accept non-conflicting changes and collect differences
+ Iterable<Diff> nonConflictingDifferences = acceptNonConflictingChanges(comparison, filter);
+ assertEquals(hasNonConflictingDiffs, !isEmpty(nonConflictingDifferences));
+
+ // get conflicting diffs
+ final List<Diff> conflictingDifferences = getConflictingDifferences(
+ Lists.newArrayList(nonConflictingDifferences), Lists.newArrayList(realConflicts));
+ assertEquals(hasConflictingDiffs, !conflictingDifferences.isEmpty());
+
+ // all accepted differences have been merged
+ assertTrue(all(nonConflictingDifferences, hasState(MERGED)));
+
+ // any differences part of real conflicts are still unresolved
+ assertTrue(all(conflictingDifferences, hasState(UNRESOLVED)));
+
+ // assert new structure (right changes merged into left for non-conflicts)
+ EObject root = getLeftUMLRoot(comparison);
+ assertNotNull(root);
+ assertTrue(root instanceof Model);
+ Model model = (Model)root;
+ Package package1 = (Package)model.getPackagedElement("Package1");
+ assertNotNull(package1);
+ PackageableElement class1 = package1.getPackagedElement("Class1");
+ assertNull(class1); // still null due to conflict
+ PackageableElement class2 = package1.getPackagedElement("Class2");
+ if (filter == FILTER_OFF) {
+ assertNotNull(class2);
+ Class class2class = (Class)class2;
+ assertTrue(class2class.getGeneralizations().isEmpty()); // no generalization added due to conflict
+ } else {
+ assertNull(class2); // class not added, because sub-diffs are in conflict
+ }
+ }
+
+ /**
+ * Returns the root element of the left UML resource or null if no such element can be found.
+ *
+ * @param comparison
+ * comparison
+ * @return left root element
+ */
+ protected static EObject getLeftUMLRoot(Comparison comparison) {
+ for (MatchResource resource : comparison.getMatchedResources()) {
+ if (resource.getLeft().getURI().lastSegment().endsWith("uml")) {
+ return resource.getLeft().getContents().get(0);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Accepts all non-conflicting changes. The left changes will be accepted and the right changes will be
+ * merged into the left-hand side.
+ *
+ * @param comparison
+ * comparison with differences
+ * @param leftToRight
+ * direction of merge
+ * @return affected differences
+ */
+ protected static Iterable<Diff> acceptNonConflictingChanges(Comparison comparison,
+ boolean cascadingFilter) {
+ boolean leftToRight = false;
+ boolean isLeftEditable = true;
+ boolean isRightEditable = false;
+ setCascadingFilter(cascadingFilter);
+ MergeNonConflictingRunnable mergeNonConflicting = new MergeNonConflictingRunnable(isLeftEditable,
+ isRightEditable, MergeMode.ACCEPT, null);
+ Iterable<Diff> mergedDiffs = mergeNonConflicting.merge(comparison, leftToRight, MERGER_REGISTRY);
+ restoreCascadingFilter();
+ return mergedDiffs;
+ }
+
+ /**
+ * Returns a list of all differences that part of a conflict and ensures that there is no overlap between
+ * conflicting and non-conflicting diffs.
+ *
+ * @param realConflicts
+ * conflicts
+ * @return conflicting differences
+ */
+ protected static List<Diff> getConflictingDifferences(List<Diff> nonConflictingDiffs,
+ List<Conflict> realConflicts) {
+ ArrayList<Diff> conflictingDiffs = Lists.newArrayList();
+ for (Conflict conflict : realConflicts) {
+ EList<Diff> conflctDiffs = conflict.getDifferences();
+ conflictingDiffs.addAll(conflctDiffs);
+ }
+
+ // assert no overlap between non-conflicting and conflicting
+ assertFalse(nonConflictingDiffs.removeAll(conflictingDiffs));
+ assertFalse(conflictingDiffs.removeAll(nonConflictingDiffs));
+
+ return conflictingDiffs;
+ }
+
+ /**
+ * Sets the cascading filter option (subdiff-awareness) of all mergers to the given state. Any changes
+ * done by this method can be restored by calling {@link #restoreCascadingFilter()}.
+ *
+ * @param enabled
+ * filter state
+ */
+ protected static void setCascadingFilter(boolean enabled) {
+ for (IMergeOptionAware merger : Iterables.filter(MERGER_REGISTRY.getMergers(null),
+ IMergeOptionAware.class)) {
+ Map<Object, Object> mergeOptions = merger.getMergeOptions();
+ Object previousValue = mergeOptions.get(SUB_DIFF_AWARE_OPTION);
+ CACHED_OPTIONS.put(merger, previousValue);
+ mergeOptions.put(SUB_DIFF_AWARE_OPTION, Boolean.valueOf(enabled));
+ }
+ }
+
+ /**
+ * Restores the cascading filter options changed by the last call to {@link #enableCascadingFilter()},
+ * {@link #disableCascadingFilter()}, or {@link #setCascadingFilter(boolean)}.
+ */
+ protected static void restoreCascadingFilter() {
+ // restore previous values
+ for (Entry<IMergeOptionAware, Object> entry : CACHED_OPTIONS.entrySet()) {
+ IMergeOptionAware merger = entry.getKey();
+ merger.getMergeOptions().put(SUB_DIFF_AWARE_OPTION, entry.getValue());
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/left/left.di b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/left/left.di
new file mode 100644
index 000000000..bf9abab34
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/left/left.di
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"/>
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/left/left.notation b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/left/left.notation
new file mode 100644
index 000000000..17aac1777
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/left/left.notation
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<notation:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:style="http://www.eclipse.org/papyrus/infra/viewpoints/policy/style" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_e5YrAC8QEeacdOKGfrvgBQ" type="PapyrusUMLClassDiagram" name="ClassDiagram" measurementUnit="Pixel">
+ <children xmi:type="notation:Shape" xmi:id="_h6JtUC8QEeacdOKGfrvgBQ" type="2007">
+ <children xmi:type="notation:DecorationNode" xmi:id="_h6MJkC8QEeacdOKGfrvgBQ" type="5026">
+ <element xmi:type="uml:Package" href="left.uml#_h585AC8QEeacdOKGfrvgBQ"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_h6MJkS8QEeacdOKGfrvgBQ" type="7016">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_h6MwoC8QEeacdOKGfrvgBQ"/>
+ <element xmi:type="uml:Package" href="left.uml#_h585AC8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_h6MwoS8QEeacdOKGfrvgBQ"/>
+ </children>
+ <element xmi:type="uml:Package" href="left.uml#_h585AC8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_h6JtUS8QEeacdOKGfrvgBQ" x="74" y="37" width="381" height="426"/>
+ </children>
+ <styles xmi:type="notation:StringValueStyle" xmi:id="_e5YrAS8QEeacdOKGfrvgBQ" name="diagram_compatibility_version" stringValue="1.1.0"/>
+ <styles xmi:type="notation:DiagramStyle" xmi:id="_e5YrAi8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="style:PapyrusViewStyle" xmi:id="_e5YrAy8QEeacdOKGfrvgBQ">
+ <owner xmi:type="uml:Model" href="left.uml#_X6atwC8QEeacdOKGfrvgBQ"/>
+ </styles>
+ <element xmi:type="uml:Model" href="left.uml#_X6atwC8QEeacdOKGfrvgBQ"/>
+</notation:Diagram>
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/left/left.uml b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/left/left.uml
new file mode 100644
index 000000000..dd04d3c22
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/left/left.uml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_X6atwC8QEeacdOKGfrvgBQ" name="RootElement">
+ <packagedElement xmi:type="uml:Package" xmi:id="_h585AC8QEeacdOKGfrvgBQ" name="Package1"/>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/origin/ancestor.di b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/origin/ancestor.di
new file mode 100644
index 000000000..bf9abab34
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/origin/ancestor.di
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"/>
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/origin/ancestor.notation b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/origin/ancestor.notation
new file mode 100644
index 000000000..f03a8dffc
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/origin/ancestor.notation
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<notation:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:style="http://www.eclipse.org/papyrus/infra/viewpoints/policy/style" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_e5YrAC8QEeacdOKGfrvgBQ" type="PapyrusUMLClassDiagram" name="ClassDiagram" measurementUnit="Pixel">
+ <children xmi:type="notation:Shape" xmi:id="_h6JtUC8QEeacdOKGfrvgBQ" type="2007">
+ <children xmi:type="notation:DecorationNode" xmi:id="_h6MJkC8QEeacdOKGfrvgBQ" type="5026"/>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_h6MJkS8QEeacdOKGfrvgBQ" type="7016">
+ <children xmi:type="notation:Shape" xmi:id="_m-JLoC8QEeacdOKGfrvgBQ" type="3010">
+ <children xmi:type="notation:DecorationNode" xmi:id="_m-JysC8QEeacdOKGfrvgBQ" type="5014"/>
+ <children xmi:type="notation:DecorationNode" xmi:id="_m-JysS8QEeacdOKGfrvgBQ" type="8518">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_m-Jysi8QEeacdOKGfrvgBQ" y="5"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_m-LA0C8QEeacdOKGfrvgBQ" type="7011">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_m-LA0S8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_m-LA0i8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_m-LA0y8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_m-LA1C8QEeacdOKGfrvgBQ"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_m-LA1S8QEeacdOKGfrvgBQ" type="7012">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_m-LA1i8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_m-LA1y8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_m-LA2C8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_m-LA2S8QEeacdOKGfrvgBQ"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_m-LA2i8QEeacdOKGfrvgBQ" type="7013">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_m-LA2y8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_m-LA3C8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_m-LA3S8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_m-LA3i8QEeacdOKGfrvgBQ"/>
+ </children>
+ <element xmi:type="uml:Class" href="ancestor.uml#_m-BP0C8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_m-JLoS8QEeacdOKGfrvgBQ" x="135" y="26"/>
+ </children>
+ <styles xmi:type="notation:TitleStyle" xmi:id="_h6MwoC8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_h6MwoS8QEeacdOKGfrvgBQ"/>
+ </children>
+ <element xmi:type="uml:Package" href="ancestor.uml#_h585AC8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_h6JtUS8QEeacdOKGfrvgBQ" x="74" y="37" width="381" height="426"/>
+ </children>
+ <styles xmi:type="notation:StringValueStyle" xmi:id="_e5YrAS8QEeacdOKGfrvgBQ" name="diagram_compatibility_version" stringValue="1.1.0"/>
+ <styles xmi:type="notation:DiagramStyle" xmi:id="_e5YrAi8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="style:PapyrusViewStyle" xmi:id="_e5YrAy8QEeacdOKGfrvgBQ">
+ <owner xmi:type="uml:Model" href="ancestor.uml#_X6atwC8QEeacdOKGfrvgBQ"/>
+ </styles>
+ <element xmi:type="uml:Model" href="ancestor.uml#_X6atwC8QEeacdOKGfrvgBQ"/>
+</notation:Diagram>
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/origin/ancestor.uml b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/origin/ancestor.uml
new file mode 100644
index 000000000..6829615c1
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/origin/ancestor.uml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_X6atwC8QEeacdOKGfrvgBQ" name="RootElement">
+ <packagedElement xmi:type="uml:Package" xmi:id="_h585AC8QEeacdOKGfrvgBQ" name="Package1">
+ <packagedElement xmi:type="uml:Class" xmi:id="_m-BP0C8QEeacdOKGfrvgBQ" name="Class1"/>
+ </packagedElement>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/right/right.di b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/right/right.di
new file mode 100644
index 000000000..bf9abab34
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/right/right.di
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"/>
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/right/right.notation b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/right/right.notation
new file mode 100644
index 000000000..d58f1ca5a
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/right/right.notation
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<notation:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:style="http://www.eclipse.org/papyrus/infra/viewpoints/policy/style" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_e5YrAC8QEeacdOKGfrvgBQ" type="PapyrusUMLClassDiagram" name="ClassDiagram" measurementUnit="Pixel">
+ <children xmi:type="notation:Shape" xmi:id="_h6JtUC8QEeacdOKGfrvgBQ" type="2007">
+ <children xmi:type="notation:DecorationNode" xmi:id="_h6MJkC8QEeacdOKGfrvgBQ" type="5026">
+ <element xmi:type="uml:Package" href="right.uml#_h585AC8QEeacdOKGfrvgBQ"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_h6MJkS8QEeacdOKGfrvgBQ" type="7016">
+ <children xmi:type="notation:Shape" xmi:id="_m-JLoC8QEeacdOKGfrvgBQ" type="3010">
+ <children xmi:type="notation:DecorationNode" xmi:id="_m-JysC8QEeacdOKGfrvgBQ" type="5014">
+ <element xmi:type="uml:Class" href="right.uml#_m-BP0C8QEeacdOKGfrvgBQ"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_m-JysS8QEeacdOKGfrvgBQ" type="8518">
+ <element xmi:type="uml:Class" href="right.uml#_m-BP0C8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_m-Jysi8QEeacdOKGfrvgBQ" y="5"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_m-LA0C8QEeacdOKGfrvgBQ" type="7011">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_m-LA0S8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_m-LA0i8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_m-LA0y8QEeacdOKGfrvgBQ"/>
+ <element xmi:type="uml:Class" href="right.uml#_m-BP0C8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_m-LA1C8QEeacdOKGfrvgBQ"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_m-LA1S8QEeacdOKGfrvgBQ" type="7012">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_m-LA1i8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_m-LA1y8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_m-LA2C8QEeacdOKGfrvgBQ"/>
+ <element xmi:type="uml:Class" href="right.uml#_m-BP0C8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_m-LA2S8QEeacdOKGfrvgBQ"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_m-LA2i8QEeacdOKGfrvgBQ" type="7013">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_m-LA2y8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_m-LA3C8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_m-LA3S8QEeacdOKGfrvgBQ"/>
+ <element xmi:type="uml:Class" href="right.uml#_m-BP0C8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_m-LA3i8QEeacdOKGfrvgBQ"/>
+ </children>
+ <element xmi:type="uml:Class" href="right.uml#_m-BP0C8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_m-JLoS8QEeacdOKGfrvgBQ" x="135" y="26"/>
+ </children>
+ <children xmi:type="notation:Shape" xmi:id="_26D1wC8QEeacdOKGfrvgBQ" type="3010">
+ <children xmi:type="notation:DecorationNode" xmi:id="_26Fq8C8QEeacdOKGfrvgBQ" type="5014"/>
+ <children xmi:type="notation:DecorationNode" xmi:id="_26Fq8S8QEeacdOKGfrvgBQ" type="8518">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_26Fq8i8QEeacdOKGfrvgBQ" y="5"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_26Fq8y8QEeacdOKGfrvgBQ" type="7011">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_26Fq9C8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_26Fq9S8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_26Fq9i8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_26Fq9y8QEeacdOKGfrvgBQ"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_26Fq-C8QEeacdOKGfrvgBQ" type="7012">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_26Fq-S8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_26Fq-i8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_26Fq-y8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_26Fq_C8QEeacdOKGfrvgBQ"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_26Fq_S8QEeacdOKGfrvgBQ" type="7013">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_26Fq_i8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_26Fq_y8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_26FrAC8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_26FrAS8QEeacdOKGfrvgBQ"/>
+ </children>
+ <element xmi:type="uml:Class" href="right.uml#_259vIC8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_26D1wS8QEeacdOKGfrvgBQ" x="135" y="247"/>
+ </children>
+ <styles xmi:type="notation:TitleStyle" xmi:id="_h6MwoC8QEeacdOKGfrvgBQ"/>
+ <element xmi:type="uml:Package" href="right.uml#_h585AC8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_h6MwoS8QEeacdOKGfrvgBQ"/>
+ </children>
+ <element xmi:type="uml:Package" href="right.uml#_h585AC8QEeacdOKGfrvgBQ"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_h6JtUS8QEeacdOKGfrvgBQ" x="74" y="37" width="381" height="426"/>
+ </children>
+ <styles xmi:type="notation:StringValueStyle" xmi:id="_e5YrAS8QEeacdOKGfrvgBQ" name="diagram_compatibility_version" stringValue="1.1.0"/>
+ <styles xmi:type="notation:DiagramStyle" xmi:id="_e5YrAi8QEeacdOKGfrvgBQ"/>
+ <styles xmi:type="style:PapyrusViewStyle" xmi:id="_e5YrAy8QEeacdOKGfrvgBQ">
+ <owner xmi:type="uml:Model" href="right.uml#_X6atwC8QEeacdOKGfrvgBQ"/>
+ </styles>
+ <element xmi:type="uml:Model" href="right.uml#_X6atwC8QEeacdOKGfrvgBQ"/>
+ <edges xmi:type="notation:Connector" xmi:id="_8W-xcC8QEeacdOKGfrvgBQ" type="4002" source="_26D1wC8QEeacdOKGfrvgBQ" target="_m-JLoC8QEeacdOKGfrvgBQ">
+ <children xmi:type="notation:DecorationNode" xmi:id="_8W_YgC8QEeacdOKGfrvgBQ" type="6007">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_8W_YgS8QEeacdOKGfrvgBQ" y="40"/>
+ </children>
+ <styles xmi:type="notation:FontStyle" xmi:id="_8W-xcS8QEeacdOKGfrvgBQ"/>
+ <element xmi:type="uml:Generalization" href="right.uml#_8W21oC8QEeacdOKGfrvgBQ"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_8W-xci8QEeacdOKGfrvgBQ" points="[-1, -7, 1, 134]$[-4, -128, -2, 13]"/>
+ <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_8XoRsC8QEeacdOKGfrvgBQ" id="(0.46,0.0)"/>
+ <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_8XoRsS8QEeacdOKGfrvgBQ" id="(0.45,1.0)"/>
+ </edges>
+</notation:Diagram>
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/right/right.uml b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/right/right.uml
new file mode 100644
index 000000000..51e98e25f
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/classes/right/right.uml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_X6atwC8QEeacdOKGfrvgBQ" name="RootElement">
+ <packagedElement xmi:type="uml:Package" xmi:id="_h585AC8QEeacdOKGfrvgBQ" name="Package1">
+ <packagedElement xmi:type="uml:Class" xmi:id="_m-BP0C8QEeacdOKGfrvgBQ" name="Class1"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_259vIC8QEeacdOKGfrvgBQ" name="Class2">
+ <generalization xmi:type="uml:Generalization" xmi:id="_8W21oC8QEeacdOKGfrvgBQ" general="_m-BP0C8QEeacdOKGfrvgBQ"/>
+ </packagedElement>
+ </packagedElement>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/ecore/left/left.ecore b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/ecore/left/left.ecore
new file mode 100644
index 000000000..0d46cfee6
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/ecore/left/left.ecore
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
+ name="Package1"/>
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/ecore/origin/ancestor.ecore b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/ecore/origin/ancestor.ecore
new file mode 100644
index 000000000..dafdd97bd
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/ecore/origin/ancestor.ecore
@@ -0,0 +1,5 @@
+<?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="Package1">
+ <eClassifiers xsi:type="ecore:EClass" name="Class1"/>
+</ecore:EPackage>
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/ecore/right/right.ecore b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/ecore/right/right.ecore
new file mode 100644
index 000000000..77fea6515
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/structuremergeviewer/actions/data/bug487151/ecore/right/right.ecore
@@ -0,0 +1,21 @@
+<?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="Package1"
+ nsURI=""
+ nsPrefix="">
+ <eClassifiers
+ xsi:type="ecore:EClass"
+ name="Class1"/>
+ <eClassifiers
+ xsi:type="ecore:EClass"
+ name="Class2">
+ <eStructuralFeatures
+ xsi:type="ecore:EAttribute"
+ name="Generalization"
+ eType="#//Class1"/>
+ </eClassifiers>
+</ecore:EPackage>
diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/suite/AllTests.java b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/suite/AllTests.java
index e01bb7284..2d7bca99c 100644
--- a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/suite/AllTests.java
+++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/suite/AllTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013, 2016 Obeo and others.
+ * Copyright (c) 2013, 2017 Obeo and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -9,6 +9,7 @@
* Obeo - initial API and implementation
* Stefan Dirix - add ModelExtensionUtil, SaveParameterHook and URIAttachment tests
* Philip Langer - add IngoreDiFileModelElementsTest
+ * Martin Fleck - add MergeNonConflictingCascadingDifferencesFilterTest
*******************************************************************************/
package org.eclipse.emf.compare.diagram.papyrus.tests.suite;
@@ -24,6 +25,7 @@ import org.eclipse.emf.compare.diagram.papyrus.tests.merge.NodeMergeTest;
import org.eclipse.emf.compare.diagram.papyrus.tests.modelextension.ModelExtensionUtilTest;
import org.eclipse.emf.compare.diagram.papyrus.tests.saveparameter.SaveParameterHookIntegrationTest;
import org.eclipse.emf.compare.diagram.papyrus.tests.saveparameter.SaveParameterHookTest;
+import org.eclipse.emf.compare.diagram.papyrus.tests.structuremergeviewer.actions.MergeNonConflictingCascadingFilterTest;
import org.eclipse.emf.compare.diagram.papyrus.tests.uriattachment.URIAttachmentTest;
import org.eclipse.emf.compare.tests.suite.CompareTestSuite;
import org.eclipse.emf.ecore.EPackage;
@@ -53,7 +55,8 @@ import junit.textui.TestRunner;
@SuiteClasses({AssocMergeTest.class, EdgeMergeTest.class, NodeMergeTest.class, ModelExtensionUtilTest.class,
SaveParameterHookTest.class, SaveParameterHookIntegrationTest.class, URIAttachmentTest.class,
DiagramTooltipProviderTest.class, PapyrusConflictsGroupProviderTests.class,
- IgnoreDiFilePostProcessorTest.class, PapyrusContextUtilTest.class })
+ IgnoreDiFilePostProcessorTest.class, PapyrusContextUtilTest.class,
+ MergeNonConflictingCascadingFilterTest.class })
public class AllTests {
/**
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/ConflictDetectionTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/ConflictDetectionTest.java
index c88fb7951..258233138 100644
--- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/ConflictDetectionTest.java
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/ConflictDetectionTest.java
@@ -1931,6 +1931,22 @@ public class ConflictDetectionTest {
}
@Test
+ public void testE3UseCase() throws IOException {
+ final Resource left = input.getE3Left();
+ final Resource origin = input.getE3Origin();
+ final Resource right = input.getE3Right();
+
+ final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+ final Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+ final List<Diff> differences = comparison.getDifferences();
+ final List<Conflict> conflicts = comparison.getConflicts();
+
+ assertEquals(3, differences.size());
+ assertEquals(1, conflicts.size());
+ }
+
+ @Test
public void testFUseCase() throws IOException {
final Resource left = input.getFLeft();
final Resource origin = input.getFOrigin();
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/ConflictInputData.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/ConflictInputData.java
index 4438a5369..396b70b30 100644
--- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/ConflictInputData.java
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/ConflictInputData.java
@@ -544,6 +544,18 @@ public class ConflictInputData extends AbstractInputData {
return loadFromClassLoader("e2/conflict_e2_right.nodes");
}
+ public Resource getE3Left() throws IOException {
+ return loadFromClassLoader("e3/conflict_e3_left.nodes");
+ }
+
+ public Resource getE3Origin() throws IOException {
+ return loadFromClassLoader("e3/conflict_e3_origin.nodes");
+ }
+
+ public Resource getE3Right() throws IOException {
+ return loadFromClassLoader("e3/conflict_e3_right.nodes");
+ }
+
public Resource getFLeft() throws IOException {
return loadFromClassLoader("f/conflict_f_left.nodes");
}
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/e3/conflict_e3_left.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/e3/conflict_e3_left.nodes
new file mode 100644
index 000000000..818e238da
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/e3/conflict_e3_left.nodes
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"
+ xmi:id="_SSvAAJQ_EeGUu8zWDEISZA"
+ name="root"/>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/e3/conflict_e3_origin.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/e3/conflict_e3_origin.nodes
new file mode 100644
index 000000000..f31a847a7
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/e3/conflict_e3_origin.nodes
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node
+ xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"
+ xmi:id="_SSvAAJQ_EeGUu8zWDEISZA"
+ name="root">
+ <containmentRef1
+ xmi:id="_iQJe8JQ_EeGUu8zWDEISZA"
+ name="origin"/>
+</nodes:Node>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/e3/conflict_e3_right.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/e3/conflict_e3_right.nodes
new file mode 100644
index 000000000..e2802cdb4
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/e3/conflict_e3_right.nodes
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<nodes:Node xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes" xmi:id="_SSvAAJQ_EeGUu8zWDEISZA" name="root">
+ <containmentRef1 xmi:id="_iQJe8JQ_EeGUu8zWDEISZA" name="origin"/>
+ <containmentRef1 xsi:type="nodes:NodeSingleValueReference" xmi:id="_kT6GcJQ_EeGUu8zWDEISZA" name="conflictHolder" singleValuedReference="_iQJe8JQ_EeGUu8zWDEISZA"/>
+</nodes:Node>
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/useCases b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/useCases
index 037dabf81..08c00b00b 100644
--- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/useCases
+++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/useCases
@@ -36,6 +36,7 @@ These only apply to reference changes
e - Adding reference towards deleted Notifier.
e1 - Within single-valued reference.
e2 - Within multi-valued reference.
+ e3 - Add a single-valued reference on the right side to a node that has been deleted on the left side.
f - Changing containment feature of Notifier to two distinct features in left and right.
g - Changing container of Notifier to two distinct Notifiers in left and right.
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ComputeDiffsToMerge.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ComputeDiffsToMerge.java
index c1469d570..3d8590238 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ComputeDiffsToMerge.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ComputeDiffsToMerge.java
@@ -17,12 +17,10 @@ import static org.eclipse.emf.compare.merge.IMergeCriterion.NONE;
import com.google.common.base.Predicate;
import com.google.common.collect.Sets;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
-import java.util.List;
import java.util.Set;
import org.eclipse.emf.compare.Conflict;
@@ -144,7 +142,7 @@ public class ComputeDiffsToMerge {
* The diff to merge
*/
protected void addDiff(Diff diff) {
- addDiffs(Collections.singleton(diff));
+ addDiffs(Collections.singleton(diff), Sets.<Diff> newLinkedHashSet());
}
/**
@@ -153,16 +151,18 @@ public class ComputeDiffsToMerge {
*
* @param diffs
* The diffs to merge at the current step of the computation
+ * @param diffPath
+ * The path that lead to a diff
*/
- protected void addDiffs(Collection<Diff> diffs) {
+ protected void addDiffs(Collection<Diff> diffs, Set<Diff> diffPath) {
if (diffs.isEmpty()) {
return;
}
Set<Diff> consequences = new LinkedHashSet<Diff>();
for (Diff diff : diffs) {
- addDiff(diff, consequences);
+ addDiff(diff, consequences, diffPath);
}
- addDiffs(Sets.difference(consequences, result));
+ addDiffs(Sets.difference(consequences, result), diffPath);
}
/**
@@ -173,21 +173,22 @@ public class ComputeDiffsToMerge {
* The diff to add
* @param consequences
* The set of diffs that must be merged at the next step.
+ * @param diffPath
+ * The path that lead to the diff to add
*/
- protected void addDiff(Diff diff, Set<Diff> consequences) {
+ protected void addDiff(Diff diff, Set<Diff> consequences, Set<Diff> diffPath) {
if (!result.contains(diff) && computing.add(diff)) {
+ diffPath.add(diff);
Conflict conflict = diff.getConflict();
if (conflictChecker != null && conflict != null && !conflictChecker.apply(conflict)
&& diff.getConflict().getKind() == REAL) {
- List<Diff> diffsThatLedToConflict = new ArrayList<Diff>(result);
- diffsThatLedToConflict.add(diff);
- throw new MergeBlockedByConflictException(diffsThatLedToConflict);
+ throw new MergeBlockedByConflictException(diffPath);
}
if (relationshipComputer.hasMerger(diff)) {
Set<Diff> dependencies = relationshipComputer.getDirectMergeDependencies(diff, rightToLeft);
for (Diff required : dependencies) {
- addDiff(required, consequences);
+ addDiff(required, consequences, Sets.newLinkedHashSet(diffPath));
}
result.add(diff);

Back to the top