Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTanja Mayerhofer2016-10-10 14:42:45 -0400
committerTanja Mayerhofer2016-10-11 04:52:41 -0400
commit78e37cb0bbd9d806af97dfdae8f48db30a5d1cf7 (patch)
tree121a909742da3a2fc79217aae2060551e2056b4e
parent8fcb916fb0f3ae13630d9b4603e2286767d0878a (diff)
downloadorg.eclipse.emf.compare-78e37cb0bbd9d806af97dfdae8f48db30a5d1cf7.tar.gz
org.eclipse.emf.compare-78e37cb0bbd9d806af97dfdae8f48db30a5d1cf7.tar.xz
org.eclipse.emf.compare-78e37cb0bbd9d806af97dfdae8f48db30a5d1cf7.zip
[501864] Adapts diff filters for conflicting refined diffs
If a refined diff has a direct or indirect real conflict or all its refining diffs have pseudo conflicts, they should not be shown in the difference groups (left/right side). However, refined diffs that are redefined by both diffs that have pseudo conflicts and diffs that do not have any conflicts should be shown in the difference groups. Bug: 501864 Change-Id: I9dd640e3736d0ca98ef194965ee8f62a3404c06c Signed-off-by: Tanja Mayerhofer <tmayerhofer@eclipsesource.com>
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui.tests/META-INF/MANIFEST.MF3
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/groups/ConflictsGroupTest.java491
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/groups/ConflictsGroupWithRefinedDiffTestScenario.java84
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/filters/impl/TechnicalitiesFilter.java7
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/impl/ThreeWayComparisonGroupProvider.java47
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/EMFComparePredicates.java17
6 files changed, 603 insertions, 46 deletions
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui.tests/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.compare.rcp.ui.tests/META-INF/MANIFEST.MF
index 1d85c0799..172d73c65 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui.tests/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.compare.rcp.ui.tests/META-INF/MANIFEST.MF
@@ -11,7 +11,8 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.emf.compare.edit;bundle-version="3.0.0",
org.eclipse.emf.compare.tests;bundle-version="2.1.0",
org.eclipse.emf.compare.rcp;bundle-version="2.1.0",
- org.eclipse.emf.compare.rcp.ui;bundle-version="3.0.0"
+ org.eclipse.emf.compare.rcp.ui;bundle-version="3.0.0",
+ org.eclipse.jface
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-Vendor: %providerName
Import-Package: com.google.common.base;version="[11.0.0,16.0.0)",
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/groups/ConflictsGroupTest.java b/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/groups/ConflictsGroupTest.java
index d0c5cf89b..9e064ff72 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/groups/ConflictsGroupTest.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/groups/ConflictsGroupTest.java
@@ -11,58 +11,56 @@
*******************************************************************************/
package org.eclipse.emf.compare.rcp.ui.tests.structuremergeviewer.groups;
-import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasConflict;
+import static com.google.common.base.Predicates.and;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
-import java.util.Collection;
import java.util.List;
-import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.compare.CompareFactory;
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.provider.spec.CompareItemProviderAdapterFactorySpec;
+import org.eclipse.emf.compare.DifferenceSource;
import org.eclipse.emf.compare.rcp.ui.internal.EMFCompareRCPUIMessages;
+import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.filters.StructureMergeViewerFilter;
+import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.filters.impl.TechnicalitiesFilter;
+import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl.BasicDifferenceGroupImpl;
+import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl.ThreeWayComparisonGroupProvider;
import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl.ThreeWayComparisonGroupProvider.ConflictsGroupImpl;
import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl.ThreeWayComparisonGroupProvider.ConflictsGroupImpl.CompositeConflict;
import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.nodes.ConflictNode;
+import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.nodes.DiffNode;
+import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.nodes.MatchNode;
import org.eclipse.emf.compare.rcp.ui.tests.structuremergeviewer.groups.provider.AbstractTestTreeNodeItemProviderAdapter;
+import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.provider.EcoreItemProviderAdapterFactory;
import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
-import org.eclipse.emf.edit.provider.AdapterFactoryItemDelegator;
-import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
-import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
import org.eclipse.emf.edit.tree.TreeNode;
import org.eclipse.emf.edit.tree.TreePackage;
import org.junit.Test;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
+import com.google.common.eventbus.EventBus;
@SuppressWarnings("restriction")
public class ConflictsGroupTest extends AbstractTestTreeNodeItemProviderAdapter {
private static final CompareFactory FACTORY = CompareFactory.eINSTANCE;
- private AdapterFactoryItemDelegator itemDelegator;
+ private ECrossReferenceAdapter crossReferenceAdapter;
@Override
public void before() throws IOException {
super.before();
-
- final Collection<AdapterFactory> factories = Lists.newArrayList();
- factories.add(new CompareItemProviderAdapterFactorySpec());
- factories.add(treeItemProviderAdapterFactory);
- factories.add(new EcoreItemProviderAdapterFactory());
- factories.add(new ReflectiveItemProviderAdapterFactory());
-
- final AdapterFactory composedAdapterFactory = new ComposedAdapterFactory(factories);
- itemDelegator = new AdapterFactoryItemDelegator(composedAdapterFactory);
+ crossReferenceAdapter = new TestECrossReferenceAdapter();
}
/**
@@ -109,22 +107,7 @@ public class ConflictsGroupTest extends AbstractTestTreeNodeItemProviderAdapter
comparison.getConflicts().add(conflict3);
// Build conflict nodes
- ECrossReferenceAdapter crossReferenceAdapter = new ECrossReferenceAdapter() {
- /**
- * {@inheritDoc}
- *
- * @see org.eclipse.emf.ecore.util.ECrossReferenceAdapter#isIncluded(org.eclipse.emf.ecore.EReference)
- */
- @Override
- protected boolean isIncluded(EReference eReference) {
- return eReference == TreePackage.Literals.TREE_NODE__DATA;
- }
- };
- final ConflictsGroupImpl conflictsGroup = new ConflictsGroupImpl(comparison,
- hasConflict(ConflictKind.REAL, ConflictKind.PSEUDO),
- EMFCompareRCPUIMessages.getString("ThreeWayComparisonGroupProvider.conflicts.label"), //$NON-NLS-1$
- crossReferenceAdapter);
- conflictsGroup.buildSubTree();
+ final ConflictsGroupImpl conflictsGroup = buildConflictGroup(comparison);
// One conflict node was created
List<? extends TreeNode> conflictNodes = conflictsGroup.getChildren();
@@ -201,7 +184,443 @@ public class ConflictsGroupTest extends AbstractTestTreeNodeItemProviderAdapter
assertEquals(ConflictKind.PSEUDO, mergedConflictGroup.getKind());
}
- protected void checkText(TreeNode childNode, String expected) {
- assertEquals(expected, itemDelegator.getText(childNode));
+ /**
+ * Tests that a refined diff whose refinding diffs are involved in a real conflict
+ * {@link ConflictKind#REAL} is only shown in the conflicts group but not in the left or right diff group.
+ * This test is related to <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=501864"</a>
+ */
+ @Test
+ public void testRefinedDiffsWithRealConflictsAreOnlyInConflictGroup() {
+ ConflictsGroupWithRefinedDiffTestScenario scenario = new ConflictsGroupWithRefinedDiffTestScenario();
+
+ // Create real conflict between refining diffs
+ final Conflict conflict = scenario.addConflict(scenario.diff1b, scenario.diff2b, ConflictKind.REAL);
+
+ // Build conflict nodes
+ final ConflictsGroupImpl conflictsGroup = buildConflictGroup(scenario.comparison);
+
+ // One conflict node was created
+ final List<? extends TreeNode> conflictNodes = conflictsGroup.getChildren();
+ assertEquals(1, conflictNodes.size());
+
+ // The conflict node is associated with the created conflict
+ final ConflictNode conflictNode = (ConflictNode)conflictNodes.get(0);
+ final CompositeConflict conflictNodeConflict = (CompositeConflict)conflictNode.basicGetData();
+ assertEquals(1, conflictNodeConflict.getConflicts().size());
+ assertTrue(conflictNodeConflict.getConflicts().contains(conflict));
+
+ // The conflict node contains diff nodes for the refined diffs
+ assertEquals(1, conflictNode.getChildren().size());
+ final MatchNode matchNode = (MatchNode)conflictNode.getChildren().get(0);
+ assertTrue(matchNodeContainsDiffNodesForDiffs(matchNode, scenario.diff1, scenario.diff2));
+
+ // The technicalities filter does not filter this conflict, because there is a real conflict between
+ // the refining diffs
+ final List<? extends TreeNode> conflictDiffNodesFiltered = applyTechnicalitiesFilter(
+ matchNode.getChildren());
+ assertEquals(2, conflictDiffNodesFiltered.size());
+
+ // Build left side
+ final BasicDifferenceGroupImpl leftSide = buildDifferenceGroup(scenario.comparison,
+ DifferenceSource.LEFT);
+
+ // There are no diffs in the left side
+ assertEquals(0, leftSide.getChildren().size());
+
+ // Build right side
+ final BasicDifferenceGroupImpl rightSide = buildDifferenceGroup(scenario.comparison,
+ DifferenceSource.RIGHT);
+
+ // There are no diffs in the right side
+ assertEquals(0, rightSide.getChildren().size());
+ }
+
+ /**
+ * Tests that a refined diff whose refining diffs are involved in a real conflict
+ * {@link ConflictKind#REAL} and in a pseudo conflict {@link ConflictKind#REAL} is only shown in the
+ * conflicts group but not in the left or right diff group. This test is related to <a
+ * href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=501864"</a>
+ */
+ @Test
+ public void testRefinedDiffsWithRealAndPseudoConflictsAreOnlyInConflictGroup() {
+ ConflictsGroupWithRefinedDiffTestScenario scenario = new ConflictsGroupWithRefinedDiffTestScenario();
+
+ // Create real conflict between refining diffs
+ final Conflict conflictReal = scenario.addConflict(scenario.diff1b, scenario.diff2b,
+ ConflictKind.REAL);
+
+ // Create pseudo conflict between refining diffs
+ final Conflict conflictPseudo = scenario.addConflict(scenario.diff1a, scenario.diff2a,
+ ConflictKind.PSEUDO);
+
+ // Build conflict nodes
+ final ConflictsGroupImpl conflictsGroup = buildConflictGroup(scenario.comparison);
+
+ // One conflict node was created
+ final List<? extends TreeNode> conflictNodes = conflictsGroup.getChildren();
+ assertEquals(1, conflictNodes.size());
+
+ // The conflict node is associated with the created conflicts
+ final ConflictNode conflictNode = (ConflictNode)conflictNodes.get(0);
+ final CompositeConflict conflictNodeConflict = (CompositeConflict)conflictNode.basicGetData();
+ assertEquals(2, conflictNodeConflict.getConflicts().size());
+ assertTrue(conflictNodeConflict.getConflicts().contains(conflictReal));
+ assertTrue(conflictNodeConflict.getConflicts().contains(conflictPseudo));
+
+ // The conflict node contains diff nodes for the refined diffs
+ assertEquals(1, conflictNode.getChildren().size());
+ final MatchNode matchNode = (MatchNode)conflictNode.getChildren().get(0);
+ assertTrue(matchNodeContainsDiffNodesForDiffs(matchNode, scenario.diff1, scenario.diff2));
+
+ // The technicalities filter does not filter this conflict, because there is a real conflict between
+ // the refining diffs
+ final List<? extends TreeNode> conflictDiffNodesFiltered = applyTechnicalitiesFilter(
+ matchNode.getChildren());
+ assertEquals(2, conflictDiffNodesFiltered.size());
+
+ // Build left side
+ final BasicDifferenceGroupImpl leftSide = buildDifferenceGroup(scenario.comparison,
+ DifferenceSource.LEFT);
+
+ // There are no diffs in the left side
+ assertEquals(0, leftSide.getChildren().size());
+
+ // Build right side
+ final BasicDifferenceGroupImpl rightSide = buildDifferenceGroup(scenario.comparison,
+ DifferenceSource.RIGHT);
+
+ // There are no diffs in the right side
+ assertEquals(0, rightSide.getChildren().size());
+ }
+
+ /**
+ * Tests that a refined diff that is refined by diffs who are all involved in pseudo conflicts
+ * {@link ConflictKind#REAL} is only shown in the conflicts group but not in the left or right diff group.
+ * This test is related to <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=501864"</a>
+ */
+ @Test
+ public void testRefinedDiffsWithOnlyPseudoConflictsAreOnlyInConflictGroup() {
+ ConflictsGroupWithRefinedDiffTestScenario scenario = new ConflictsGroupWithRefinedDiffTestScenario();
+
+ // Create pseudo conflicts between refining diffs
+ final Conflict conflictPseudo1 = scenario.addConflict(scenario.diff1b, scenario.diff2b,
+ ConflictKind.PSEUDO);
+ final Conflict conflictPseudo2 = scenario.addConflict(scenario.diff1a, scenario.diff2a,
+ ConflictKind.PSEUDO);
+
+ // Build conflict nodes
+ final ConflictsGroupImpl conflictsGroup = buildConflictGroup(scenario.comparison);
+
+ // One conflict node was created
+ final List<? extends TreeNode> conflictNodes = conflictsGroup.getChildren();
+ assertEquals(1, conflictNodes.size());
+
+ // The conflict node is associated with the created conflicts
+ final ConflictNode conflictNode = (ConflictNode)conflictNodes.get(0);
+ final CompositeConflict conflictNodeConflict = (CompositeConflict)conflictNode.basicGetData();
+ assertEquals(2, conflictNodeConflict.getConflicts().size());
+ assertTrue(conflictNodeConflict.getConflicts().contains(conflictPseudo1));
+ assertTrue(conflictNodeConflict.getConflicts().contains(conflictPseudo2));
+
+ // The conflict node contains diff nodes for the refined diffs
+ assertEquals(1, conflictNode.getChildren().size());
+ final MatchNode matchNode = (MatchNode)conflictNode.getChildren().get(0);
+ assertTrue(matchNodeContainsDiffNodesForDiffs(matchNode, scenario.diff1, scenario.diff2));
+
+ // The technicalities filter filters this conflict, since the involved refined diffs are refined by
+ // diffs that are all involved in pseudo conflicts
+ final List<? extends TreeNode> conflictDiffNodesFiltered = applyTechnicalitiesFilter(
+ matchNode.getChildren());
+ assertEquals(0, conflictDiffNodesFiltered.size());
+
+ // Build left side
+ final BasicDifferenceGroupImpl leftSide = buildDifferenceGroup(scenario.comparison,
+ DifferenceSource.LEFT);
+
+ // There are no diffs in the left side
+ assertEquals(0, leftSide.getChildren().size());
+
+ // Build right side
+ final BasicDifferenceGroupImpl rightSide = buildDifferenceGroup(scenario.comparison,
+ DifferenceSource.RIGHT);
+
+ // There are no diffs in the right side
+ assertEquals(0, rightSide.getChildren().size());
+ }
+
+ /**
+ * Tests that a refined diff that is refined by one diff involved in a pseudo conflict
+ * {@link ConflictKind#PSEUDO} and one diff involved in no conflict is shown in the conflicts group and in
+ * the left or right diff group. This test is related to <a
+ * href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=501864"</a>
+ */
+ @Test
+ public void testRefinedDiffsWithOnlyOnePseudoConflictAreInConflictGroupAndDiffGroup() {
+ ConflictsGroupWithRefinedDiffTestScenario scenario = new ConflictsGroupWithRefinedDiffTestScenario();
+
+ // Create pseudo conflict
+ final Conflict conflictPseudo = scenario.addConflict(scenario.diff1b, scenario.diff2b,
+ ConflictKind.PSEUDO);
+
+ // Build conflict nodes
+ final ConflictsGroupImpl conflictsGroup = buildConflictGroup(scenario.comparison);
+
+ // One conflict node was created
+ List<? extends TreeNode> conflictNodes = conflictsGroup.getChildren();
+ assertEquals(1, conflictNodes.size());
+
+ // The conflict node is associated with the created conflict
+ ConflictNode conflictNode = (ConflictNode)conflictNodes.get(0);
+ CompositeConflict conflictNodeConflict = (CompositeConflict)conflictNode.basicGetData();
+ assertEquals(1, conflictNodeConflict.getConflicts().size());
+ assertTrue(conflictNodeConflict.getConflicts().contains(conflictPseudo));
+
+ // The conflict node contains diff nodes for the refined diffs
+ assertEquals(1, conflictNode.getChildren().size());
+ MatchNode matchNode = (MatchNode)conflictNode.getChildren().get(0);
+ assertTrue(matchNodeContainsDiffNodesForDiffs(matchNode, scenario.diff1, scenario.diff2));
+
+ // The technicalities filter does not filter this conflict, because it involved a refined diff that is
+ // refined by a diff that is not involved in a conflict
+ final List<? extends TreeNode> conflictDiffNodesFiltered = applyTechnicalitiesFilter(
+ matchNode.getChildren());
+ assertEquals(2, conflictDiffNodesFiltered.size());
+
+ // Build left side
+ final BasicDifferenceGroupImpl leftSide = buildDifferenceGroup(scenario.comparison,
+ DifferenceSource.LEFT);
+
+ // There is one refined diff in the left side, which is refined by one diff that is not in a conflict
+ // and one diff that is in a PSEUDO conflict
+ assertEquals(1, leftSide.getChildren().size());
+ MatchNode matchNodeLeft = (MatchNode)leftSide.getChildren().get(0);
+ assertTrue(matchNodeContainsDiffNodesForDiffs(matchNodeLeft, scenario.diff1));
+
+ // The technicalities filter does not filter the changes on the left side, because the refined diff is
+ // refined by a diff that is not involved in a conflict
+ final List<? extends TreeNode> diffNodesLeftFiltered = applyTechnicalitiesFilter(
+ matchNodeLeft.getChildren());
+ assertEquals(1, diffNodesLeftFiltered.size());
+ final List<? extends TreeNode> subDiffNodesLeftFiltered = applyTechnicalitiesFilter(
+ diffNodesLeftFiltered.get(0).getChildren());
+ assertEquals(1, subDiffNodesLeftFiltered.size());
+
+ // Build right side
+ final BasicDifferenceGroupImpl rightSide = buildDifferenceGroup(scenario.comparison,
+ DifferenceSource.RIGHT);
+
+ // There is one refined diff in the right side, which is refined by one diff that is not in a conflict
+ // and one diff that is in a PSEUDO conflict
+ assertEquals(1, rightSide.getChildren().size());
+ MatchNode matchNodeRight = (MatchNode)rightSide.getChildren().get(0);
+ assertTrue(matchNodeContainsDiffNodesForDiffs(matchNodeRight, scenario.diff2));
+
+ // The technicalities filter does not filter the changes on the right side, because the refined diff
+ // is refined by a diff that is not involved in a conflict
+ final List<? extends TreeNode> diffNodesRightFiltered = applyTechnicalitiesFilter(
+ matchNodeRight.getChildren());
+ assertEquals(1, diffNodesRightFiltered.size());
+ final List<? extends TreeNode> subDiffNodesRightFiltered = applyTechnicalitiesFilter(
+ diffNodesRightFiltered.get(0).getChildren());
+ assertEquals(1, subDiffNodesRightFiltered.size());
+ }
+
+ /**
+ * Tests that a refined diff that is directly involved in a pseudo conflict {@link ConflictKind#PSEUDO}
+ * and that is refined by one diff involved in a real conflict {@link ConflictKind#REAL} is shown in the
+ * conflicts group. This test is related to <a
+ * href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=501864"</a>
+ */
+ @Test
+ public void testRefinedDiffsInPseudoConflictAndWithRefiningDiffsInRealConflictAreInConflictGroup() {
+ ConflictsGroupWithRefinedDiffTestScenario scenario = new ConflictsGroupWithRefinedDiffTestScenario();
+
+ // Create pseudo conflict
+ final Conflict conflictPseudo = scenario.addConflict(scenario.diff1, scenario.diff2,
+ ConflictKind.PSEUDO);
+
+ // Create real conflict
+ final Conflict conflictReal = scenario.addConflict(scenario.diff1b, scenario.diff2b,
+ ConflictKind.REAL);
+
+ // Build conflict nodes
+ final ConflictsGroupImpl conflictsGroup = buildConflictGroup(scenario.comparison);
+
+ // One conflict node was created
+ List<? extends TreeNode> conflictNodes = conflictsGroup.getChildren();
+ assertEquals(1, conflictNodes.size());
+
+ // The conflict node is associated with both created conflicts
+ ConflictNode conflictNode = (ConflictNode)conflictNodes.get(0);
+ CompositeConflict conflictNodeConflict = (CompositeConflict)conflictNode.basicGetData();
+ assertEquals(2, conflictNodeConflict.getConflicts().size());
+ assertTrue(conflictNodeConflict.getConflicts().contains(conflictPseudo));
+ assertTrue(conflictNodeConflict.getConflicts().contains(conflictReal));
+
+ // The conflict node contains diff nodes for the refined diffs
+ assertEquals(1, conflictNode.getChildren().size());
+ MatchNode matchNode = (MatchNode)conflictNode.getChildren().get(0);
+ assertTrue(matchNodeContainsDiffNodesForDiffs(matchNode, scenario.diff1, scenario.diff2));
+
+ // The technicalities filter does not filter this conflict, because there is a real conflict between
+ // the refining diffs
+ final List<? extends TreeNode> conflictDiffNodesFiltered = applyTechnicalitiesFilter(
+ matchNode.getChildren());
+ assertEquals(2, conflictDiffNodesFiltered.size());
+
+ // Build left side
+ final BasicDifferenceGroupImpl leftSide = buildDifferenceGroup(scenario.comparison,
+ DifferenceSource.LEFT);
+
+ // There are no diffs in the left side
+ assertEquals(0, leftSide.getChildren().size());
+
+ // Build right side
+ final BasicDifferenceGroupImpl rightSide = buildDifferenceGroup(scenario.comparison,
+ DifferenceSource.RIGHT);
+
+ // There are no diffs in the right side
+ assertEquals(0, rightSide.getChildren().size());
+ }
+
+ /**
+ * Tests that a refined diff that is neither directly nor indirect involved in any conflict is shown in
+ * the left or right diff group. This test is related to <a
+ * href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=501864"</a>
+ */
+ @Test
+ public void testRefinedDiffsWithoutConfictsAreInDiffGroup() {
+ ConflictsGroupWithRefinedDiffTestScenario scenario = new ConflictsGroupWithRefinedDiffTestScenario();
+
+ // Build conflict nodes
+ final ConflictsGroupImpl conflictsGroup = buildConflictGroup(scenario.comparison);
+
+ // No conflict node was created
+ assertEquals(0, conflictsGroup.getChildren().size());
+
+ // Build left side
+ final BasicDifferenceGroupImpl leftSide = buildDifferenceGroup(scenario.comparison,
+ DifferenceSource.LEFT);
+
+ // There is one refined diff in the left side, which is neither directly nor indirectly involved in a
+ // conflict
+ assertEquals(1, leftSide.getChildren().size());
+ MatchNode matchNodeLeft = (MatchNode)leftSide.getChildren().get(0);
+ assertTrue(matchNodeContainsDiffNodesForDiffs(matchNodeLeft, scenario.diff1));
+
+ // The technicalities filter does not filter the changes on the left side, because they are not
+ // involved in conflicts
+ final List<? extends TreeNode> diffNodesLeftFiltered = applyTechnicalitiesFilter(
+ matchNodeLeft.getChildren());
+ assertEquals(1, diffNodesLeftFiltered.size());
+ final List<? extends TreeNode> subDiffNodesLeftFiltered = applyTechnicalitiesFilter(
+ diffNodesLeftFiltered.get(0).getChildren());
+ assertEquals(2, subDiffNodesLeftFiltered.size());
+
+ // Build right side
+ final BasicDifferenceGroupImpl rightSide = buildDifferenceGroup(scenario.comparison,
+ DifferenceSource.RIGHT);
+
+ // There is one refined diff in the right side, which is neither directly nor indirectly involved in a
+ // conflict
+ assertEquals(1, rightSide.getChildren().size());
+ MatchNode matchNodeRight = (MatchNode)rightSide.getChildren().get(0);
+ assertTrue(matchNodeContainsDiffNodesForDiffs(matchNodeRight, scenario.diff2));
+
+ // The technicalities filter does not filter the changes on the right side, because they are not
+ // involved in conflicts
+ final List<? extends TreeNode> diffNodesRightFiltered = applyTechnicalitiesFilter(
+ matchNodeRight.getChildren());
+ assertEquals(1, diffNodesRightFiltered.size());
+ final List<? extends TreeNode> subDiffNodesRightFiltered = applyTechnicalitiesFilter(
+ diffNodesRightFiltered.get(0).getChildren());
+ assertEquals(2, subDiffNodesRightFiltered.size());
+
+ }
+
+ private class TestECrossReferenceAdapter extends ECrossReferenceAdapter {
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.ecore.util.ECrossReferenceAdapter#isIncluded(org.eclipse.emf.ecore.EReference)
+ */
+ @Override
+ protected boolean isIncluded(EReference eReference) {
+ return eReference == TreePackage.Literals.TREE_NODE__DATA;
+ }
+ }
+
+ private ConflictsGroupImpl buildConflictGroup(Comparison comparison) {
+ final ConflictsGroupImpl conflictsGroup = new ConflictsGroupImpl(comparison,
+ EMFCompareRCPUIMessages.getString("ThreeWayComparisonGroupProvider.conflicts.label"), //$NON-NLS-1$
+ crossReferenceAdapter);
+ conflictsGroup.buildSubTree();
+ return conflictsGroup;
+ }
+
+ private BasicDifferenceGroupImpl buildDifferenceGroup(Comparison comparison, DifferenceSource source) {
+ final BasicDifferenceGroupImpl differenceGroup = new BasicDifferenceGroupImpl(comparison,
+ and(fromSide(source), ThreeWayComparisonGroupProvider.DEFAULT_DIFF_GROUP_FILTER_PREDICATE),
+ "", crossReferenceAdapter);
+ differenceGroup.buildSubTree();
+ return differenceGroup;
+ }
+
+ private boolean matchNodeContainsDiffNodesForDiffs(MatchNode matchNode, Diff... diffs) {
+ final boolean matchNodeContainsRightAmountOfChildren = matchNode.getChildren().size() == diffs.length;
+ boolean matchNodeContainsDiffNodesForDiffs = true;
+ for (Diff diff : diffs) {
+ DiffNode diffNode = getDiffNode(matchNode.getChildren(), diff);
+ if (!isDiffNodeForDiff(diffNode, diff)) {
+ matchNodeContainsDiffNodesForDiffs = false;
+ }
+ }
+ return matchNodeContainsRightAmountOfChildren && matchNodeContainsDiffNodesForDiffs;
+ }
+
+ private DiffNode getDiffNode(EList<TreeNode> nodes, Diff diff) {
+ for (TreeNode node : nodes) {
+ if (node instanceof DiffNode) {
+ DiffNode diffNode = (DiffNode)node;
+ if (diffNode.basicGetData() == diff) {
+ return diffNode;
+ }
+ }
+ }
+ return null;
+ }
+
+ private boolean isDiffNodeForDiff(DiffNode diffNode, Diff diff) {
+ if (diffNode == null || diff == null) {
+ return false;
+ }
+ final boolean diffNodeAssociatedWithDiff = diffNode.basicGetData() == diff;
+ final boolean diffNodeContainsRightAmountOfChildren = diffNode.getChildren().size() == diff
+ .getRefinedBy().size();
+ boolean diffNodeContainsNodesForRefiningDiffs = true;
+ for (Diff refiningDiff : diff.getRefinedBy()) {
+ final DiffNode diffNodeForRefiningDiff = getDiffNode(diffNode.getChildren(), refiningDiff);
+ if (diffNodeForRefiningDiff == null) {
+ diffNodeContainsNodesForRefiningDiffs = false;
+ }
+ }
+ return diffNodeAssociatedWithDiff && diffNodeContainsRightAmountOfChildren
+ && diffNodeContainsNodesForRefiningDiffs;
+ }
+
+ private List<? extends TreeNode> applyTechnicalitiesFilter(List<? extends TreeNode> actualTrees) {
+ final StructureMergeViewerFilter filter = new StructureMergeViewerFilter(new EventBus());
+ final TechnicalitiesFilter technicalitiesFilter = new TechnicalitiesFilter();
+ filter.addFilter(technicalitiesFilter);
+ Predicate<EObject> viewerFilterPredicate = new Predicate<EObject>() {
+ public boolean apply(EObject input) {
+ AdapterImpl adapter = new AdapterImpl();
+ adapter.setTarget(input);
+ return filter.select(null, null, adapter);
+ }
+ };
+ List<? extends TreeNode> filteredTrees = Lists
+ .newArrayList(Collections2.filter(actualTrees, viewerFilterPredicate));
+ return filteredTrees;
}
}
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/groups/ConflictsGroupWithRefinedDiffTestScenario.java b/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/groups/ConflictsGroupWithRefinedDiffTestScenario.java
new file mode 100644
index 000000000..e271b0288
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/groups/ConflictsGroupWithRefinedDiffTestScenario.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2016 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:
+ * Tanja Mayerhofer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.emf.compare.rcp.ui.tests.structuremergeviewer.groups;
+
+import org.eclipse.emf.compare.CompareFactory;
+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.DifferenceSource;
+import org.eclipse.emf.compare.Match;
+
+public class ConflictsGroupWithRefinedDiffTestScenario {
+
+ private static final CompareFactory FACTORY = CompareFactory.eINSTANCE;
+
+ final Diff diff1;
+
+ final Diff diff1a;
+
+ final Diff diff1b;
+
+ final Diff diff2;
+
+ final Diff diff2a;
+
+ final Diff diff2b;
+
+ final Comparison comparison;
+
+ public ConflictsGroupWithRefinedDiffTestScenario() {
+ // Create diffs left side
+ diff1 = FACTORY.createDiff();
+ diff1a = FACTORY.createDiff();
+ diff1b = FACTORY.createDiff();
+ diff1.getRefinedBy().add(diff1a);
+ diff1.getRefinedBy().add(diff1b);
+
+ diff1.setSource(DifferenceSource.LEFT);
+ diff1a.setSource(DifferenceSource.LEFT);
+ diff1b.setSource(DifferenceSource.LEFT);
+
+ // Create diffs right side
+ diff2 = FACTORY.createDiff();
+ diff2a = FACTORY.createDiff();
+ diff2b = FACTORY.createDiff();
+ diff2.getRefinedBy().add(diff2a);
+ diff2.getRefinedBy().add(diff2b);
+
+ diff2.setSource(DifferenceSource.RIGHT);
+ diff2a.setSource(DifferenceSource.RIGHT);
+ diff2b.setSource(DifferenceSource.RIGHT);
+
+ // Create comparison
+ comparison = FACTORY.createComparison();
+ comparison.setThreeWay(true);
+ final Match match1 = FACTORY.createMatch();
+ match1.getDifferences().add(diff1);
+ match1.getDifferences().add(diff1a);
+ match1.getDifferences().add(diff1b);
+ match1.getDifferences().add(diff2);
+ match1.getDifferences().add(diff2a);
+ match1.getDifferences().add(diff2b);
+ comparison.getMatches().add(match1);
+ }
+
+ Conflict addConflict(Diff conflictingDiff1, Diff conflictingDiff2, ConflictKind kind) {
+ final Conflict conflict = FACTORY.createConflict();
+ conflict.getDifferences().add(conflictingDiff1);
+ conflict.getDifferences().add(conflictingDiff2);
+ conflict.setKind(kind);
+ comparison.getConflicts().add(conflict);
+ return conflict;
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/filters/impl/TechnicalitiesFilter.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/filters/impl/TechnicalitiesFilter.java
index 4053b3813..3f6ca3871 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/filters/impl/TechnicalitiesFilter.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/filters/impl/TechnicalitiesFilter.java
@@ -8,11 +8,14 @@
* Contributors:
* Obeo - initial API and implementation
* Philip Langer - bug 501864
+ * Tanja Mayerhofer - bug 501864
*******************************************************************************/
package org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.filters.impl;
import static com.google.common.collect.Iterators.any;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.anyRefiningDiffs;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasDirectOrIndirectConflict;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasNoDirectOrIndirectConflict;
import com.google.common.base.Predicate;
@@ -111,7 +114,9 @@ public class TechnicalitiesFilter extends AbstractDifferenceFilter {
*/
private static boolean hasDirectOrIndirectPseudoConflictOnly(Diff diff) {
return hasDirectOrIndirectConflict(ConflictKind.PSEUDO).apply(diff)
- && !hasDirectOrIndirectConflict(ConflictKind.REAL).apply(diff);
+ && !hasDirectOrIndirectConflict(ConflictKind.REAL).apply(diff)
+ && !anyRefiningDiffs(hasNoDirectOrIndirectConflict(ConflictKind.REAL, ConflictKind.PSEUDO))
+ .apply(diff);
}
/**
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/impl/ThreeWayComparisonGroupProvider.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/impl/ThreeWayComparisonGroupProvider.java
index c31ee5d4d..33d722705 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/impl/ThreeWayComparisonGroupProvider.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/impl/ThreeWayComparisonGroupProvider.java
@@ -15,18 +15,21 @@ package org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.and;
+import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterators.concat;
import static com.google.common.collect.Iterators.filter;
import static com.google.common.collect.Iterators.transform;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.anyRefiningDiffs;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasConflict;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasDirectOrIndirectConflict;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasNoDirectOrIndirectConflict;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasState;
import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
@@ -76,6 +79,15 @@ import org.eclipse.emf.ecore.util.EcoreUtil;
public class ThreeWayComparisonGroupProvider extends AbstractDifferenceGroupProvider {
/**
+ * The default predicate used to filter differences in difference groups. The predicate returns true for
+ * diffs that do not have a direct or indirect real conflict and that do not have only pseudo conflicts.
+ */
+ public static final Predicate<? super Diff> DEFAULT_DIFF_GROUP_FILTER_PREDICATE = and(
+ not(hasDirectOrIndirectConflict(ConflictKind.REAL)),
+ not(and(anyRefiningDiffs(hasConflict(ConflictKind.PSEUDO)), not(anyRefiningDiffs(
+ hasNoDirectOrIndirectConflict(ConflictKind.PSEUDO, ConflictKind.REAL))))));
+
+ /**
* {@inheritDoc}
*
* @see org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider#isEnabled(org
@@ -97,6 +109,12 @@ public class ThreeWayComparisonGroupProvider extends AbstractDifferenceGroupProv
public static class ConflictsGroupImpl extends BasicDifferenceGroupImpl {
/**
+ * The default predicate used to filter differences.
+ */
+ private static final Predicate<? super Diff> DEFAULT_CONFLICT_GROUP_FILTER_PREDICATE = hasConflict(
+ ConflictKind.REAL, ConflictKind.PSEUDO);
+
+ /**
* Conflict groups to show in SMV.
*/
private final List<CompositeConflict> compositeConflicts = newArrayList();
@@ -118,6 +136,22 @@ public class ThreeWayComparisonGroupProvider extends AbstractDifferenceGroupProv
}
/**
+ * Instantiates this group given the comparison. It will use the default filter to determine its list
+ * of differences. It will be displayed in the UI with the default icon and the given name.
+ *
+ * @param comparison
+ * The comparison that is the parent of this group.
+ * @param name
+ * The name that the EMF Compare UI will display for this group.
+ * @param crossReferenceAdapter
+ * The cross reference adapter that will be added to this group's children.
+ */
+ public ConflictsGroupImpl(Comparison comparison, String name,
+ ECrossReferenceAdapter crossReferenceAdapter) {
+ super(comparison, DEFAULT_CONFLICT_GROUP_FILTER_PREDICATE, name, crossReferenceAdapter);
+ }
+
+ /**
* In conflicts, a special case must be handled for refining diffs: If they are not part of the same
* conflict then they should not be in the same group as the refined diff.
*
@@ -340,21 +374,18 @@ public class ThreeWayComparisonGroupProvider extends AbstractDifferenceGroupProv
}
final ConflictsGroupImpl conflicts = new ConflictsGroupImpl(getComparison(),
- hasConflict(ConflictKind.REAL, ConflictKind.PSEUDO),
EMFCompareRCPUIMessages.getString("ThreeWayComparisonGroupProvider.conflicts.label"), //$NON-NLS-1$
getCrossReferenceAdapter());
conflicts.buildSubTree();
final BasicDifferenceGroupImpl leftSide = new BasicDifferenceGroupImpl(getComparison(),
- Predicates.and(fromSide(DifferenceSource.LEFT),
- Predicates.not(hasConflict(ConflictKind.REAL, ConflictKind.PSEUDO))),
- leftLabel, getCrossReferenceAdapter());
+ and(fromSide(DifferenceSource.LEFT), DEFAULT_DIFF_GROUP_FILTER_PREDICATE), leftLabel,
+ getCrossReferenceAdapter());
leftSide.buildSubTree();
final BasicDifferenceGroupImpl rightSide = new BasicDifferenceGroupImpl(getComparison(),
- Predicates.and(fromSide(DifferenceSource.RIGHT),
- Predicates.not(hasConflict(ConflictKind.REAL, ConflictKind.PSEUDO))),
- rightLabel, getCrossReferenceAdapter());
+ and(fromSide(DifferenceSource.RIGHT), DEFAULT_DIFF_GROUP_FILTER_PREDICATE), rightLabel,
+ getCrossReferenceAdapter());
rightSide.buildSubTree();
return ImmutableList.of(conflicts, leftSide, rightSide);
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/EMFComparePredicates.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/EMFComparePredicates.java
index c0fe3b8ee..97d88cf8d 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/EMFComparePredicates.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/EMFComparePredicates.java
@@ -9,11 +9,13 @@
* Obeo - initial API and implementation
* Stefan Dirix - bug 441172
* Philip Langer - add additional predicates
+ * Tanja Mayerhofer - bug 501864
*******************************************************************************/
package org.eclipse.emf.compare.utils;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.and;
+import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Iterators.any;
import static org.eclipse.emf.compare.internal.utils.ComparisonUtil.isDeleteOrUnsetDiff;
@@ -1169,6 +1171,21 @@ public final class EMFComparePredicates {
}
/**
+ * This predicate can be used to check whether a diff is not in a conflict directly or indirectly.
+ * <p>
+ * A diff is directly in a conflict if it {@link #hasConflict(ConflictKind...) has a conflict}. A diff is
+ * indirectly in a conflict, if one of its refining diffs is in a conflict.
+ * </p>
+ *
+ * @param kinds
+ * Type(s) of the conflict(s) we seek.
+ * @return The created predicate.
+ */
+ public static Predicate<? super Diff> hasNoDirectOrIndirectConflict(final ConflictKind... kinds) {
+ return and(not(hasConflict(kinds)), not(anyRefiningDiffs(hasConflict(kinds))));
+ }
+
+ /**
* This particular predicate will be used to check that a given Diff corresponds to a ReferenceChange on a
* given reference, with known "original" and "changed" values.
*

Back to the top