diff options
16 files changed, 460 insertions, 6 deletions
diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/Bug484557ConflictTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/Bug484557ConflictTest.java new file mode 100644 index 000000000..5f8035f42 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/Bug484557ConflictTest.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (c) 2015 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.emf.compare.tests.conflict.data.bug484557; + +import static org.eclipse.emf.compare.DifferenceKind.DELETE; +import static org.eclipse.emf.compare.DifferenceSource.LEFT; +import static org.eclipse.emf.compare.DifferenceSource.RIGHT; +import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide; +import static org.junit.Assert.assertEquals; +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 java.io.IOException; +import java.util.List; + +import org.eclipse.emf.compare.AttributeChange; +import org.eclipse.emf.compare.Comparison; +import org.eclipse.emf.compare.Conflict; +import org.eclipse.emf.compare.Diff; +import org.eclipse.emf.compare.DifferenceSource; +import org.eclipse.emf.compare.EMFCompare; +import org.eclipse.emf.compare.ReferenceChange; +import org.eclipse.emf.compare.ResourceAttachmentChange; +import org.eclipse.emf.compare.scope.DefaultComparisonScope; +import org.eclipse.emf.compare.scope.IComparisonScope; +import org.eclipse.emf.compare.utils.EMFComparePredicates; +import org.eclipse.emf.ecore.resource.Resource; +import org.junit.Ignore; +import org.junit.Test; + +/** + * This class tests that conflicts between ResourceAttachmentChanges of type DELETE and other changes made to + * the element that was a root of a resource are seen as conflicts when necessary. See bug 484557 for more + * details. + * + * @author <a href="mailto:laurent.delaigue@obeo.fr">Laurent Delaigue</a> + */ +public class Bug484557ConflictTest { + + private Conflict484557InputData input = new Conflict484557InputData(); + + @Test + public void testAttributeConflict() throws IOException { + final Resource ancestor = input.getAttributeAncestorResource(); + final Resource left = input.getAttributeLeftResource(); + final Resource right = input.getAttributeRightResource(); + + final IComparisonScope scope = new DefaultComparisonScope(left, right, ancestor); + final Comparison comparison = EMFCompare.builder().build().compare(scope); + + final List<Diff> differences = comparison.getDifferences(); + final List<Conflict> conflicts = comparison.getConflicts(); + + assertEquals(2, differences.size()); + assertEquals(1, conflicts.size()); + assertTrue(conflicts.get(0).getDifferences().containsAll(differences)); + + Iterable<ResourceAttachmentChange> raChanges = Iterables.filter(differences, + ResourceAttachmentChange.class); + assertEquals(1, Iterables.size(raChanges)); + assertEquals(DifferenceSource.LEFT, raChanges.iterator().next().getSource()); + + Iterable<AttributeChange> attChanges = Iterables.filter(differences, AttributeChange.class); + assertEquals(1, Iterables.size(attChanges)); + assertEquals(DifferenceSource.RIGHT, attChanges.iterator().next().getSource()); + } + + @Test + public void testSingleReferenceConflict() throws IOException { + final Resource ancestor = input.getSingleRefAncestorResource(); + final Resource left = input.getSingleRefLeftResource(); + final Resource right = input.getSingleRefRightResource(); + + final IComparisonScope scope = new DefaultComparisonScope(left, right, ancestor); + 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()); + assertTrue(conflicts.get(0).getDifferences().containsAll(differences)); + + Iterable<ResourceAttachmentChange> raChanges = Iterables.filter(differences, + ResourceAttachmentChange.class); + assertEquals(1, Iterables.size(raChanges)); + ResourceAttachmentChange rac = raChanges.iterator().next(); + assertEquals(LEFT, rac.getSource()); + assertEquals(DELETE, rac.getKind()); + + Iterable<ReferenceChange> refChanges = Iterables.filter(differences, ReferenceChange.class); + assertEquals(2, Iterables.size(refChanges)); + assertTrue(Iterables.any(refChanges, EMFComparePredicates.fromSide(LEFT))); + assertTrue(Iterables.any(refChanges, EMFComparePredicates.fromSide(RIGHT))); + } + + @Test + public void testMultiReferenceConflict() throws IOException { + final Resource ancestor = input.getMultiRefAncestorResource(); + final Resource left = input.getMultiRefLeftResource(); + final Resource right = input.getMultiRefRightResource(); + + final IComparisonScope scope = new DefaultComparisonScope(left, right, ancestor); + 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()); + assertEquals(2, conflicts.get(0).getDifferences().size()); + + Iterable<ResourceAttachmentChange> raChanges = Iterables.filter(differences, + ResourceAttachmentChange.class); + assertEquals(1, Iterables.size(raChanges)); + ResourceAttachmentChange rac = raChanges.iterator().next(); + assertEquals(LEFT, rac.getSource()); + assertEquals(DELETE, rac.getKind()); + + Iterable<ReferenceChange> refChanges = Iterables.filter(differences, ReferenceChange.class); + assertEquals(2, Iterables.size(refChanges)); + assertTrue(Iterables.any(refChanges, fromSide(LEFT))); + assertTrue(Iterables.any(refChanges, fromSide(RIGHT))); + + // The left refChange should not be conflicting + ReferenceChange leftRefChange = Iterables.filter(refChanges, EMFComparePredicates.fromSide(LEFT)) + .iterator().next(); + assertNull(leftRefChange.getConflict()); + + // The right refChange should be conflicting with the ResourceAttachmentChange + ReferenceChange rightRefChange = Iterables.filter(refChanges, EMFComparePredicates.fromSide(RIGHT)) + .iterator().next(); + assertNotNull(rightRefChange.getConflict()); + } + + @Test + @Ignore("Need to resolve a NPE") + public void testFeatureMapConflict() throws IOException { + final Resource ancestor = input.getFeatureMapAncestorResource(); + final Resource left = input.getFeatureMapLeftResource(); + final Resource right = input.getFeatureMapRightResource(); + + final IComparisonScope scope = new DefaultComparisonScope(left, right, ancestor); + final Comparison comparison = EMFCompare.builder().build().compare(scope); + + final List<Diff> differences = comparison.getDifferences(); + final List<Conflict> conflicts = comparison.getConflicts(); + + assertEquals(7, differences.size()); + assertEquals(1, conflicts.size()); + assertEquals(6, conflicts.get(0).getDifferences().size()); + } + +} diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/Conflict484557InputData.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/Conflict484557InputData.java new file mode 100644 index 000000000..328703aad --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/Conflict484557InputData.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2015 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.emf.compare.tests.conflict.data.bug484557; + +import java.io.IOException; + +import org.eclipse.emf.compare.tests.framework.AbstractInputData; +import org.eclipse.emf.ecore.resource.Resource; + +public class Conflict484557InputData extends AbstractInputData { + + public Resource getAttributeAncestorResource() throws IOException { + return loadFromClassLoader("att_ancestor.nodes"); //$NON-NLS-1$ + } + + public Resource getAttributeLeftResource() throws IOException { + return loadFromClassLoader("att_left.nodes"); //$NON-NLS-1$ + } + + public Resource getAttributeRightResource() throws IOException { + return loadFromClassLoader("att_right.nodes"); //$NON-NLS-1$ + } + + public Resource getFeatureMapAncestorResource() throws IOException { + return loadFromClassLoader("fm_ancestor.nodes"); //$NON-NLS-1$ + } + + public Resource getFeatureMapLeftResource() throws IOException { + return loadFromClassLoader("fm_left.nodes"); //$NON-NLS-1$ + } + + public Resource getFeatureMapRightResource() throws IOException { + return loadFromClassLoader("fm_right.nodes"); //$NON-NLS-1$ + } + + public Resource getSingleRefAncestorResource() throws IOException { + return loadFromClassLoader("ref_ancestor.nodes"); //$NON-NLS-1$ + } + + public Resource getSingleRefLeftResource() throws IOException { + return loadFromClassLoader("ref_left.nodes"); //$NON-NLS-1$ + } + + public Resource getSingleRefRightResource() throws IOException { + return loadFromClassLoader("ref_right.nodes"); //$NON-NLS-1$ + } + + public Resource getMultiRefAncestorResource() throws IOException { + return loadFromClassLoader("multi_ref_ancestor.nodes"); //$NON-NLS-1$ + } + + public Resource getMultiRefLeftResource() throws IOException { + return loadFromClassLoader("multi_ref_left.nodes"); //$NON-NLS-1$ + } + + public Resource getMultiRefRightResource() throws IOException { + return loadFromClassLoader("multi_ref_right.nodes"); //$NON-NLS-1$ + } +} diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/att_ancestor.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/att_ancestor.nodes new file mode 100644 index 000000000..2c1a98dfd --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/att_ancestor.nodes @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"> + <nodes:Node xmi:id="_1uWuQOyMEeO1JodpgTFWvw" name="Root 1"/> + <nodes:Node xmi:id="_1uWuQOyMEeO1JodpgTFWaz" name="Root 2"/> +</xmi:XMI>
\ No newline at end of file diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/att_left.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/att_left.nodes new file mode 100644 index 000000000..8255b0097 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/att_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="_1uWuQOyMEeO1JodpgTFWaz" + name="Root 2"/> diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/att_right.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/att_right.nodes new file mode 100644 index 000000000..30af374d3 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/att_right.nodes @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI xmi:version="2.0" + xmlns:xmi="http://www.omg.org/XMI" + xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"> + <nodes:Node + xmi:id="_1uWuQOyMEeO1JodpgTFWvw" + name="Root 1 renamed"/> + <nodes:Node + xmi:id="_1uWuQOyMEeO1JodpgTFWaz" + name="Root 2"/> +</xmi:XMI> diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/fm_ancestor.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/fm_ancestor.nodes new file mode 100644 index 000000000..c556599a8 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/fm_ancestor.nodes @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI 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"> + <nodes:Node + xmi:id="_1uWuQOyMEeO1JodpgTFWaz" + name="Root 2"> + <containmentRef1 + xmi:id="_R8TWoLLnEeWRJankREeKLQ" + name="A"/> + <containmentRef1 + xmi:id="_SjZy4LLnEeWRJankREeKLQ" + name="B"/> + </nodes:Node> + <nodes:NodeFeatureMapNonContainment + xmi:id="_1uWuQOyMEeO1JodpgTFWvw" + name="Root 1"> + <secondKeyNC + href="#_1uWuQOyMEeO1JodpgTFWaz"/> + <firstKeyNC + href="#_R8TWoLLnEeWRJankREeKLQ"/> + </nodes:NodeFeatureMapNonContainment> +</xmi:XMI> diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/fm_left.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/fm_left.nodes new file mode 100644 index 000000000..fde43734c --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/fm_left.nodes @@ -0,0 +1,14 @@ +<?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="_1uWuQOyMEeO1JodpgTFWaz" + name="Root 2"> + <containmentRef1 + xmi:id="_R8TWoLLnEeWRJankREeKLQ" + name="A"/> + <containmentRef1 + xmi:id="_SjZy4LLnEeWRJankREeKLQ" + name="B"/> +</nodes:Node> diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/fm_right.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/fm_right.nodes new file mode 100644 index 000000000..016d2a653 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/fm_right.nodes @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI 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"> + <nodes:Node + xmi:id="_1uWuQOyMEeO1JodpgTFWaz" + name="Root 2"> + <containmentRef1 + xmi:id="_R8TWoLLnEeWRJankREeKLQ" + name="A"/> + <containmentRef1 + xmi:id="_SjZy4LLnEeWRJankREeKLQ" + name="B"/> + </nodes:Node> + <nodes:NodeFeatureMapNonContainment + xmi:id="_1uWuQOyMEeO1JodpgTFWvw" + name="Root 1"> + <secondKeyNC + href="#_1uWuQOyMEeO1JodpgTFWaz"/> + <firstKeyNC + href="#_SjZy4LLnEeWRJankREeKLQ"/> + </nodes:NodeFeatureMapNonContainment> +</xmi:XMI> diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/multi_ref_ancestor.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/multi_ref_ancestor.nodes new file mode 100644 index 000000000..9a8b7599e --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/multi_ref_ancestor.nodes @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI 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"> + <nodes:NodeMultiValueReference + xmi:id="_1uWuQOyMEeO1JodpgTFWvw" + name="Root 1" + multiValuedReference="_elCb8LLrEeWRJankREeKLQ"> + </nodes:NodeMultiValueReference> + <nodes:Node + xmi:id="_1uWuQOyMEeO1JodpgTFWaz" + name="Root 2"> + <containmentRef1 + xmi:id="_elCb8LLrEeWRJankREeKLQ" + name="A"/> + <containmentRef1 + xmi:id="_fq87ILLrEeWRJankREeKLQ" + name="B"/> + </nodes:Node> +</xmi:XMI> diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/multi_ref_left.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/multi_ref_left.nodes new file mode 100644 index 000000000..9875a47bb --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/multi_ref_left.nodes @@ -0,0 +1,14 @@ +<?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="_1uWuQOyMEeO1JodpgTFWaz" + name="Root 2"> + <containmentRef1 + xmi:id="_elCb8LLrEeWRJankREeKLQ" + name="A"/> + <containmentRef1 + xmi:id="_fq87ILLrEeWRJankREeKLQ" + name="B"/> +</nodes:Node> diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/multi_ref_right.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/multi_ref_right.nodes new file mode 100644 index 000000000..b3ffe2a62 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/multi_ref_right.nodes @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI xmi:version="2.0" + xmlns:xmi="http://www.omg.org/XMI" + xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"> + <nodes:NodeMultiValueReference + xmi:id="_1uWuQOyMEeO1JodpgTFWvw" + name="Root 1" + multiValuedReference="_elCb8LLrEeWRJankREeKLQ _fq87ILLrEeWRJankREeKLQ"/> + <nodes:Node + xmi:id="_1uWuQOyMEeO1JodpgTFWaz" + name="Root 2"> + <containmentRef1 + xmi:id="_elCb8LLrEeWRJankREeKLQ" + name="A"/> + <containmentRef1 + xmi:id="_fq87ILLrEeWRJankREeKLQ" + name="B"/> + </nodes:Node> +</xmi:XMI> diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/ref_ancestor.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/ref_ancestor.nodes new file mode 100644 index 000000000..9c7ef7a26 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/ref_ancestor.nodes @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI xmi:version="2.0" + xmlns:xmi="http://www.omg.org/XMI" + xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"> + <nodes:NodeSingleValueReference + xmi:id="_1uWuQOyMEeO1JodpgTFWvw" + name="Root 1" + singleValuedReference="_elCb8LLrEeWRJankREeKLQ"/> + <nodes:Node + xmi:id="_1uWuQOyMEeO1JodpgTFWaz" + name="Root 2"> + <containmentRef1 + xmi:id="_elCb8LLrEeWRJankREeKLQ" + name="A"/> + <containmentRef1 + xmi:id="_fq87ILLrEeWRJankREeKLQ" + name="B"/> + </nodes:Node> +</xmi:XMI> diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/ref_left.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/ref_left.nodes new file mode 100644 index 000000000..9875a47bb --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/ref_left.nodes @@ -0,0 +1,14 @@ +<?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="_1uWuQOyMEeO1JodpgTFWaz" + name="Root 2"> + <containmentRef1 + xmi:id="_elCb8LLrEeWRJankREeKLQ" + name="A"/> + <containmentRef1 + xmi:id="_fq87ILLrEeWRJankREeKLQ" + name="B"/> +</nodes:Node> diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/ref_right.nodes b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/ref_right.nodes new file mode 100644 index 000000000..c366b2a2c --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/conflict/data/bug484557/ref_right.nodes @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI xmi:version="2.0" + xmlns:xmi="http://www.omg.org/XMI" + xmlns:nodes="http://www.eclipse.org/emf/compare/tests/nodes"> + <nodes:NodeSingleValueReference + xmi:id="_1uWuQOyMEeO1JodpgTFWvw" + name="Root 1" + singleValuedReference="_fq87ILLrEeWRJankREeKLQ"/> + <nodes:Node + xmi:id="_1uWuQOyMEeO1JodpgTFWaz" + name="Root 2"> + <containmentRef1 + xmi:id="_elCb8LLrEeWRJankREeKLQ" + name="A"/> + <containmentRef1 + xmi:id="_fq87ILLrEeWRJankREeKLQ" + name="B"/> + </nodes:Node> +</xmi:XMI> 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 af90f241b..0e7647aea 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 @@ -21,6 +21,7 @@ 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.conflict.MultiLineAttributeConflictDetectionTest; +import org.eclipse.emf.compare.tests.conflict.data.bug484557.Bug484557ConflictTest; import org.eclipse.emf.compare.tests.diff.ComparisonUtilTest; import org.eclipse.emf.compare.tests.diff.DiffUtilTest; import org.eclipse.emf.compare.tests.diff.FeatureFilterTest; @@ -90,7 +91,7 @@ import org.junit.runners.Suite.SuiteClasses; FeatureFilterTest.class, ThreeWayBatchMergingTest.class, MultiLineAttributeConflictDetectionTest.class, ThreeWayTextDiffTest.class, MultiLineAttributeMergeTest.class, MonitorCancelTest.class, IdentifierEObjectMatcherTest.class, - MatchUtilFeatureContainsTest.class, RefineMergeTest.class }) + MatchUtilFeatureContainsTest.class, RefineMergeTest.class, Bug484557ConflictTest.class }) public class AllTests { /** * Standalone launcher for all of compare's tests. 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 cc16a7020..8c34d4c2c 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 @@ -52,6 +52,7 @@ import org.eclipse.emf.compare.ResourceAttachmentChange; import org.eclipse.emf.compare.ResourceLocationChange; import org.eclipse.emf.compare.internal.SubMatchIterator; import org.eclipse.emf.compare.internal.ThreeWayTextDiff; +import org.eclipse.emf.compare.internal.utils.ComparisonUtil; import org.eclipse.emf.compare.utils.IEqualityHelper; import org.eclipse.emf.compare.utils.ReferenceUtil; import org.eclipse.emf.ecore.EAttribute; @@ -911,10 +912,39 @@ public class DefaultConflictDetector implements IConflictDetector { final EObject originVal = match.getOrigin(); for (Diff candidate : candidates) { if (candidate instanceof ReferenceChange) { - // Any ReferenceChange that references the affected root is a possible conflict - final EObject candidateValue = ((ReferenceChange)candidate).getValue(); - if (candidateValue == leftVal || candidateValue == rightVal || candidateValue == originVal) { - checkResourceAttachmentConflict(comparison, diff, (ReferenceChange)candidate); + if (diff.getKind() == DifferenceKind.DELETE && match == candidate.getMatch() + && getRelatedModelElement(diff) == null) { + // The EObject that owns the changed EReference has been deleted on the other side + conflictOn(comparison, diff, candidate, ConflictKind.REAL); + } else { + // Any ReferenceChange that references the affected root is a possible conflict + final EObject candidateValue = ((ReferenceChange)candidate).getValue(); + if (candidateValue == leftVal || candidateValue == rightVal + || candidateValue == originVal) { + checkResourceAttachmentConflict(comparison, diff, (ReferenceChange)candidate); + } + } + } else if (candidate instanceof AttributeChange) { + // The change of an attribute on an EObject that has been removed from a root on the other + // side is a conflict + if (diff.getKind() == DifferenceKind.DELETE && match == candidate.getMatch() + && getRelatedModelElement(diff) == null) { + if (ComparisonUtil.isDeleteOrUnsetDiff(candidate)) { + conflictOn(comparison, diff, candidate, ConflictKind.PSEUDO); + } else { + conflictOn(comparison, diff, candidate, ConflictKind.REAL); + } + } + } else if (candidate instanceof FeatureMapChange) { + // The change of a FM on an EObject that has been removed from a root on the other side + // is a conflict + if (diff.getKind() == DifferenceKind.DELETE && match == candidate.getMatch() + && getRelatedModelElement(diff) == null) { + if (ComparisonUtil.isDeleteOrUnsetDiff(candidate)) { + conflictOn(comparison, diff, candidate, ConflictKind.PSEUDO); + } else { + conflictOn(comparison, diff, candidate, ConflictKind.REAL); + } } } else if (candidate instanceof ResourceAttachmentChange && match == candidate.getMatch()) { // This can only be a conflict. All we need to know is its kind. @@ -968,7 +998,7 @@ public class DefaultConflictDetector implements IConflictDetector { * * @param diff * The change - * @return The modele element of the given diff, or null if it cannot be found. + * @return The model element of the given diff, or null if it cannot be found. */ private EObject getRelatedModelElement(ResourceAttachmentChange diff) { Match m = diff.getMatch(); |