diff options
Diffstat (limited to 'plugins')
71 files changed, 4153 insertions, 2107 deletions
diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.papyrus/src/org/eclipse/emf/compare/diagram/ide/ui/papyrus/internal/merge/AdditivePapyrusResourceAttachmentChangeMerger.java b/plugins/org.eclipse.emf.compare.diagram.ide.ui.papyrus/src/org/eclipse/emf/compare/diagram/ide/ui/papyrus/internal/merge/AdditivePapyrusResourceAttachmentChangeMerger.java index 24360b417..c0c282a8a 100644 --- a/plugins/org.eclipse.emf.compare.diagram.ide.ui.papyrus/src/org/eclipse/emf/compare/diagram/ide/ui/papyrus/internal/merge/AdditivePapyrusResourceAttachmentChangeMerger.java +++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.papyrus/src/org/eclipse/emf/compare/diagram/ide/ui/papyrus/internal/merge/AdditivePapyrusResourceAttachmentChangeMerger.java @@ -13,7 +13,8 @@ package org.eclipse.emf.compare.diagram.ide.ui.papyrus.internal.merge; import static org.eclipse.emf.compare.DifferenceKind.DELETE; import static org.eclipse.emf.compare.DifferenceSource.LEFT; import static org.eclipse.emf.compare.DifferenceState.MERGED; -import static org.eclipse.emf.compare.DifferenceState.UNRESOLVED; + +import java.util.Set; import org.eclipse.emf.common.util.Monitor; import org.eclipse.emf.compare.Diff; @@ -45,7 +46,7 @@ public class AdditivePapyrusResourceAttachmentChangeMerger extends PapyrusResour @Override public void copyRightToLeft(Diff target, Monitor monitor) { - if (target.getState() != UNRESOLVED) { + if (isInTerminalState(target)) { return; } @@ -62,4 +63,30 @@ public class AdditivePapyrusResourceAttachmentChangeMerger extends PapyrusResour super.copyRightToLeft(target, monitor); } } + + @Override + public Set<Diff> getDirectMergeDependencies(Diff diff, boolean mergeRightToLeft) { + if (diff.getKind() == DELETE) { + if (diff.getSource() == LEFT) { + return super.getDirectMergeDependencies(diff, mergeRightToLeft); + } else { + return super.getDirectMergeDependencies(diff, !mergeRightToLeft); + } + } else { + return super.getDirectMergeDependencies(diff, mergeRightToLeft); + } + } + + @Override + public Set<Diff> getDirectResultingMerges(Diff diff, boolean mergeRightToLeft) { + if (diff.getKind() == DELETE) { + if (diff.getSource() == LEFT) { + return super.getDirectResultingMerges(diff, mergeRightToLeft); + } else { + return super.getDirectResultingMerges(diff, !mergeRightToLeft); + } + } else { + return super.getDirectResultingMerges(diff, mergeRightToLeft); + } + } } diff --git a/plugins/org.eclipse.emf.compare.diagram.ide.ui.papyrus/src/org/eclipse/emf/compare/diagram/ide/ui/papyrus/internal/merge/PapyrusResourceAttachmentChangeMerger.java b/plugins/org.eclipse.emf.compare.diagram.ide.ui.papyrus/src/org/eclipse/emf/compare/diagram/ide/ui/papyrus/internal/merge/PapyrusResourceAttachmentChangeMerger.java index f60078163..599aa246a 100644 --- a/plugins/org.eclipse.emf.compare.diagram.ide.ui.papyrus/src/org/eclipse/emf/compare/diagram/ide/ui/papyrus/internal/merge/PapyrusResourceAttachmentChangeMerger.java +++ b/plugins/org.eclipse.emf.compare.diagram.ide.ui.papyrus/src/org/eclipse/emf/compare/diagram/ide/ui/papyrus/internal/merge/PapyrusResourceAttachmentChangeMerger.java @@ -12,6 +12,7 @@ package org.eclipse.emf.compare.diagram.ide.ui.papyrus.internal.merge; import static org.eclipse.emf.compare.DifferenceSource.LEFT; import static org.eclipse.emf.compare.DifferenceSource.RIGHT; +import static org.eclipse.emf.compare.merge.IMergeCriterion.NONE; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; @@ -82,7 +83,7 @@ public class PapyrusResourceAttachmentChangeMerger extends ResourceAttachmentCha @Override public boolean apply(IMergeCriterion criterion) { - return criterion == null; + return criterion == null || criterion == NONE; } /** diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/AdditiveMergeDiagramTests.java b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/AdditiveMergeDiagramTests.java index 9e649ea2b..6997636e9 100644 --- a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/AdditiveMergeDiagramTests.java +++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/AdditiveMergeDiagramTests.java @@ -10,24 +10,19 @@ *******************************************************************************/ package org.eclipse.emf.compare.diagram.papyrus.tests.merge; -import static com.google.common.base.Predicates.not; import static com.google.common.base.Predicates.or; import static com.google.common.collect.Iterables.all; import static org.eclipse.emf.compare.ConflictKind.PSEUDO; -import static org.eclipse.emf.compare.ConflictKind.REAL; -import static org.eclipse.emf.compare.DifferenceKind.MOVE; import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasDirectOrIndirectConflict; import static org.eclipse.emf.compare.utils.EMFComparePredicates.isInRealAddAddConflict; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import java.util.Collection; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.emf.compare.Comparison; -import org.eclipse.emf.compare.Diff; import org.eclipse.emf.compare.conflict.MatchBasedConflictDetector; import org.eclipse.emf.compare.ide.ui.tests.framework.annotations.ConflictDetectors; import org.eclipse.emf.compare.ide.ui.tests.git.framework.GitMergeStrategyID; @@ -40,8 +35,6 @@ import org.eclipse.jgit.api.Status; import org.eclipse.jgit.lib.Repository; import org.junit.runner.RunWith; -import com.google.common.collect.Collections2; - @RunWith(GitTestRunner.class) @GitMergeStrategy(GitMergeStrategyID.MODEL_ADDITIVE) // FIXME DefaultConflictDetector is broken here @@ -92,18 +85,8 @@ public class AdditiveMergeDiagramTests { // package on both sides and it's (currently) impossible to guarantee // the order in which they will be placed in their parent during a merge // Let's just check that all diffs are in conflict - - Collection<Diff> diffs = Collections2.filter(comparison.getDifferences(), - not(hasDirectOrIndirectConflict(PSEUDO, REAL))); - assertEquals(2, diffs.size()); - - // Since we cannot be sure of the order of the merged element, this is possible that a side and the - // ancestor are placed in the same position and the other side is in another position, resulting in a - // move diff which is not in conflict with the expected result. This depend of the checkout branch - // when the merge is launched. - for (Diff diff : diffs) { - assertEquals(MOVE, diff.getKind()); - } + assertTrue(all(comparison.getDifferences(), + or(hasDirectOrIndirectConflict(PSEUDO), isInRealAddAddConflict()))); } @GitMerge(local = "branch2", remote = "branch1") diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/AssocMergeTest.java b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/AssocMergeTest.java index 20232e270..ad9ecada5 100644 --- a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/AssocMergeTest.java +++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/AssocMergeTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertTrue; import com.google.common.base.Predicate; import java.io.IOException; +import java.util.Arrays; import java.util.regex.Pattern; import org.eclipse.emf.common.util.BasicMonitor; @@ -36,6 +37,7 @@ import org.eclipse.emf.compare.diagram.papyrus.internal.PapyrusDiagramPostProces import org.eclipse.emf.compare.diagram.papyrus.tests.AbstractTest; import org.eclipse.emf.compare.diagram.papyrus.tests.DiagramInputData; import org.eclipse.emf.compare.diagram.papyrus.tests.merge.data.AssocMergeInputData; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.tests.postprocess.data.TestPostProcessor; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; @@ -71,7 +73,7 @@ public class AssocMergeTest extends AbstractTest { // ** MERGE ** Diff node = find(diffs, edgeTargetChangeTo("Class3")); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -97,7 +99,7 @@ public class AssocMergeTest extends AbstractTest { // ** MERGE ** Diff node = find(diffs, edgeTargetChangeTo("Class3")); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -124,7 +126,7 @@ public class AssocMergeTest extends AbstractTest { // ** MERGE ** Diff node = find(diffs, edgeTargetChangeTo("Class3")); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -151,7 +153,7 @@ public class AssocMergeTest extends AbstractTest { // ** MERGE ** Diff node = find(diffs, edgeTargetChangeTo("Class3")); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -178,7 +180,7 @@ public class AssocMergeTest extends AbstractTest { // ** MERGE ** Diff node = find(diffs, edgeTargetChangeTo("State2")); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -204,7 +206,7 @@ public class AssocMergeTest extends AbstractTest { // ** MERGE ** Diff node = find(diffs, edgeTargetChangeTo("State2")); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -234,9 +236,9 @@ public class AssocMergeTest extends AbstractTest { // ** MERGE ** Diff node = find(diffs, edgeTargetChangeTo("Class1", LEFT)); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); node = find(diffs, edgeTargetChangeTo("Class3", LEFT)); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** // left and right must now be equal @@ -267,9 +269,9 @@ public class AssocMergeTest extends AbstractTest { // ** MERGE ** Diff node = find(diffs, edgeTargetChangeTo("Class2", RIGHT)); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); node = find(diffs, edgeTargetChangeTo("Class4", RIGHT)); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** // left and right must now be equal @@ -300,7 +302,7 @@ public class AssocMergeTest extends AbstractTest { // ** MERGE ** Diff node = find(diffs, edgeTargetChangeTo("State3")); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** // left and right must now be equal @@ -331,7 +333,7 @@ public class AssocMergeTest extends AbstractTest { // ** MERGE ** Diff node = find(diffs, edgeTargetChangeTo("State4")); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** // left and right must now be equal @@ -359,9 +361,9 @@ public class AssocMergeTest extends AbstractTest { // ** MERGE ** Diff node = find(diffs, edgeTargetChangeTo("State3", LEFT)); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); node = find(diffs, edgeSourceChangeTo("State3", RIGHT)); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** // left and right must now be equal @@ -389,9 +391,9 @@ public class AssocMergeTest extends AbstractTest { // ** MERGE ** Diff node = find(diffs, edgeTargetChangeTo("Class3", LEFT)); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); node = find(diffs, edgeTargetChangeTo("Class1", RIGHT)); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** // left and right must now be equal @@ -419,9 +421,9 @@ public class AssocMergeTest extends AbstractTest { // ** MERGE ** Diff node = find(diffs, edgeTargetChangeTo("Class3", LEFT)); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); node = find(diffs, edgeTargetChangeTo("Class1", RIGHT)); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** // left and right must now be equal @@ -449,9 +451,9 @@ public class AssocMergeTest extends AbstractTest { // ** MERGE ** Diff node = find(diffs, edgeTargetChangeTo("State3", LEFT)); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); node = find(diffs, edgeSourceChangeTo("State3", RIGHT)); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** // left and right must now be equal diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/EdgeMergeTest.java b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/EdgeMergeTest.java index a0bf50ed3..7a3910cb0 100644 --- a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/EdgeMergeTest.java +++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/EdgeMergeTest.java @@ -19,6 +19,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import java.io.IOException; +import java.util.Arrays; import java.util.regex.Pattern; import org.eclipse.emf.common.util.BasicMonitor; @@ -31,6 +32,7 @@ import org.eclipse.emf.compare.diagram.internal.extensions.NodeChange; import org.eclipse.emf.compare.diagram.papyrus.tests.AbstractTest; import org.eclipse.emf.compare.diagram.papyrus.tests.DiagramInputData; import org.eclipse.emf.compare.diagram.papyrus.tests.merge.data.EdgeMergeInputData; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.tests.postprocess.data.TestPostProcessor; import org.eclipse.emf.compare.uml2.internal.AssociationChange; import org.eclipse.emf.compare.uml2.internal.DirectedRelationshipChange; @@ -219,7 +221,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyLeftToRight(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -242,7 +244,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyRightToLeft(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -266,7 +268,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyLeftToRight(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -290,7 +292,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyRightToLeft(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -313,7 +315,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), association); - getMergerRegistry().getHighestRankingMerger(associationChange).copyLeftToRight(associationChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -336,7 +338,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), association); - getMergerRegistry().getHighestRankingMerger(associationChange).copyRightToLeft(associationChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -359,7 +361,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), association); - getMergerRegistry().getHighestRankingMerger(associationChange).copyLeftToRight(associationChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -382,7 +384,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), association); - getMergerRegistry().getHighestRankingMerger(associationChange).copyRightToLeft(associationChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -407,7 +409,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyLeftToRight(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -432,7 +434,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyRightToLeft(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -458,7 +460,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyLeftToRight(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -484,7 +486,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyRightToLeft(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -509,7 +511,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), association); - getMergerRegistry().getHighestRankingMerger(associationChange).copyLeftToRight(associationChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -535,7 +537,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), association); - getMergerRegistry().getHighestRankingMerger(associationChange).copyRightToLeft(associationChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -561,7 +563,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), association); - getMergerRegistry().getHighestRankingMerger(associationChange).copyLeftToRight(associationChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -587,7 +589,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), association); - getMergerRegistry().getHighestRankingMerger(associationChange).copyRightToLeft(associationChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -613,7 +615,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyLeftToRight(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -638,7 +640,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyRightToLeft(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -664,7 +666,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyLeftToRight(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -691,7 +693,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyRightToLeft(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -716,7 +718,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), association); - getMergerRegistry().getHighestRankingMerger(associationChange).copyLeftToRight(associationChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -742,7 +744,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), association); - getMergerRegistry().getHighestRankingMerger(associationChange).copyRightToLeft(associationChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -768,7 +770,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), association); - getMergerRegistry().getHighestRankingMerger(associationChange).copyLeftToRight(associationChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -794,7 +796,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), association); - getMergerRegistry().getHighestRankingMerger(associationChange).copyRightToLeft(associationChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -824,7 +826,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge1); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyLeftToRight(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -856,7 +858,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge1); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyRightToLeft(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -885,7 +887,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge1); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyLeftToRight(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -915,7 +917,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeChange = Iterables.find(comparison.getDifferences(), edge1); - getMergerRegistry().getHighestRankingMerger(edgeChange).copyRightToLeft(edgeChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(edgeChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -950,7 +952,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), asso1); - getMergerRegistry().getHighestRankingMerger(associationChange).copyLeftToRight(associationChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -983,7 +985,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), asso1); - getMergerRegistry().getHighestRankingMerger(associationChange).copyRightToLeft(associationChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -1016,7 +1018,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), asso1); - getMergerRegistry().getHighestRankingMerger(associationChange).copyLeftToRight(associationChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -1049,7 +1051,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff associationChange = Iterables.find(comparison.getDifferences(), asso1); - getMergerRegistry().getHighestRankingMerger(associationChange).copyRightToLeft(associationChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(associationChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -1088,7 +1090,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff nodeBChange = Iterables.find(comparison.getDifferences(), nodeB); - getMergerRegistry().getHighestRankingMerger(nodeBChange).copyLeftToRight(nodeBChange, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(nodeBChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -1130,7 +1132,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff nodeBChange = Iterables.find(comparison.getDifferences(), nodeB); - getMergerRegistry().getHighestRankingMerger(nodeBChange).copyRightToLeft(nodeBChange, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(nodeBChange), new BasicMonitor()); // ** MERGE CHECKING ** @@ -1207,8 +1209,8 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edgeAbstractionChange = Iterables.find(comparison.getDifferences(), edgeAbstraction); - getMergerRegistry().getHighestRankingMerger(edgeAbstractionChange) - .copyLeftToRight(edgeAbstractionChange, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edgeAbstractionChange), + new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1289,7 +1291,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edge = Iterables.find(comparison.getDifferences(), edgeAssociation); - getMergerRegistry().getHighestRankingMerger(edge).copyLeftToRight(edge, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edge), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1369,7 +1371,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edge = Iterables.find(comparison.getDifferences(), edgeDependency); - getMergerRegistry().getHighestRankingMerger(edge).copyLeftToRight(edge, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edge), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1450,7 +1452,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edge = Iterables.find(comparison.getDifferences(), edgeImport); - getMergerRegistry().getHighestRankingMerger(edge).copyLeftToRight(edge, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edge), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1533,7 +1535,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edge = Iterables.find(comparison.getDifferences(), edgeGeneralization); - getMergerRegistry().getHighestRankingMerger(edge).copyLeftToRight(edge, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edge), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1617,7 +1619,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edge = Iterables.find(comparison.getDifferences(), edgeFlow); - getMergerRegistry().getHighestRankingMerger(edge).copyLeftToRight(edge, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edge), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1700,7 +1702,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edge = Iterables.find(comparison.getDifferences(), edgeInterfaceRealization); - getMergerRegistry().getHighestRankingMerger(edge).copyLeftToRight(edge, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edge), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1781,7 +1783,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edge = Iterables.find(comparison.getDifferences(), edgeRealization); - getMergerRegistry().getHighestRankingMerger(edge).copyLeftToRight(edge, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edge), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1862,7 +1864,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edge = Iterables.find(comparison.getDifferences(), edgeSubstitution); - getMergerRegistry().getHighestRankingMerger(edge).copyLeftToRight(edge, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edge), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1943,7 +1945,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edge = Iterables.find(comparison.getDifferences(), edgeUsage); - getMergerRegistry().getHighestRankingMerger(edge).copyLeftToRight(edge, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edge), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1988,7 +1990,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edge = Iterables.find(comparison.getDifferences(), edge1); - getMergerRegistry().getHighestRankingMerger(edge).copyLeftToRight(edge, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edge), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -2022,7 +2024,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edge = Iterables.find(comparison.getDifferences(), edge2); - getMergerRegistry().getHighestRankingMerger(edge).copyLeftToRight(edge, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edge), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -2056,7 +2058,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edge = Iterables.find(comparison.getDifferences(), edge3); - getMergerRegistry().getHighestRankingMerger(edge).copyLeftToRight(edge, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edge), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -2090,7 +2092,7 @@ public class EdgeMergeTest extends AbstractTest { // ** MERGE ** Diff edge = Iterables.find(comparison.getDifferences(), edgeTarget); - getMergerRegistry().getHighestRankingMerger(edge).copyLeftToRight(edge, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(edge), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); diff --git a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/NodeMergeTest.java b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/NodeMergeTest.java index a46dbb481..794098365 100644 --- a/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/NodeMergeTest.java +++ b/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/merge/NodeMergeTest.java @@ -27,6 +27,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import java.io.IOException; +import java.util.Arrays; import java.util.regex.Pattern; import org.eclipse.emf.common.util.BasicMonitor; @@ -45,6 +46,7 @@ import org.eclipse.emf.compare.diagram.internal.extensions.NodeChange; import org.eclipse.emf.compare.diagram.papyrus.tests.AbstractTest; import org.eclipse.emf.compare.diagram.papyrus.tests.DiagramInputData; import org.eclipse.emf.compare.diagram.papyrus.tests.merge.data.NodeMergeInputData; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.tests.postprocess.data.TestPostProcessor; import org.eclipse.emf.compare.uml2.internal.AssociationChange; import org.eclipse.emf.compare.uml2.internal.postprocessor.MultiplicityElementChangePostProcessor; @@ -156,7 +158,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), nodeA); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -233,7 +235,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), nodeA); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -311,7 +313,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), nodeA); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -388,7 +390,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), nodeA); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -465,7 +467,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), nodeB); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -536,7 +538,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), nodeB); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -609,7 +611,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), nodeB); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -680,7 +682,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), nodeB); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -754,7 +756,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), nodeSubA); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -832,7 +834,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), nodeSubA); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -906,7 +908,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), nodeSubA); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -984,7 +986,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), nodeSubA); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1027,7 +1029,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff classCDiff = Iterables.find(comparison.getDifferences(), classC); - getMergerRegistry().getHighestRankingMerger(classCDiff).copyRightToLeft(classCDiff, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(classCDiff), new BasicMonitor()); // ** MERGE CHECKING ** @@ -1067,7 +1069,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), moveNodeA); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1107,7 +1109,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), moveNodeA); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1146,7 +1148,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), moveNodeA); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1185,7 +1187,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), moveNodeA); - getMergerRegistry().getHighestRankingMerger(node).copyRightToLeft(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1212,7 +1214,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), coordinatesChangeNodeA); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); @@ -1251,7 +1253,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature4 <- ** Diff feature = Iterables.find(comparison.getDifferences(), feature4, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyRightToLeft(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1261,7 +1263,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature2 -> ** feature = Iterables.find(comparison.getDifferences(), feature2, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyLeftToRight(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1271,7 +1273,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature5 <- ** feature = Iterables.find(comparison.getDifferences(), feature5, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyRightToLeft(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1281,7 +1283,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature6 -> ** feature = Iterables.find(comparison.getDifferences(), feature6, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyLeftToRight(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1291,7 +1293,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature7 <- ** feature = Iterables.find(comparison.getDifferences(), feature7, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyRightToLeft(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1331,7 +1333,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature4 <- ** Diff feature = Iterables.find(comparison.getDifferences(), feature4, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyRightToLeft(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1341,7 +1343,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature2 -> ** feature = Iterables.find(comparison.getDifferences(), feature2, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyRightToLeft(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1351,7 +1353,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature5 <- ** feature = Iterables.find(comparison.getDifferences(), feature5, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyRightToLeft(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1361,7 +1363,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature6 -> ** feature = Iterables.find(comparison.getDifferences(), feature6, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyRightToLeft(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1371,7 +1373,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature7 <- ** feature = Iterables.find(comparison.getDifferences(), feature7, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyRightToLeft(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1411,7 +1413,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature4 <- ** Diff feature = Iterables.find(comparison.getDifferences(), feature4, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyLeftToRight(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1421,7 +1423,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature2 -> ** feature = Iterables.find(comparison.getDifferences(), feature2, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyLeftToRight(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1431,7 +1433,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature5 <- ** feature = Iterables.find(comparison.getDifferences(), feature5, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyLeftToRight(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1441,7 +1443,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature6 -> ** feature = Iterables.find(comparison.getDifferences(), feature6, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyLeftToRight(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1451,7 +1453,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE feature7 <- ** feature = Iterables.find(comparison.getDifferences(), feature7, null); assertFalse(isMergedFor3way(comparison, feature)); - getMergerRegistry().getHighestRankingMerger(feature).copyLeftToRight(feature, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(feature), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right, ancestor); @@ -1477,7 +1479,7 @@ public class NodeMergeTest extends AbstractTest { // ** MERGE ** Diff node = Iterables.find(comparison.getDifferences(), coordinatesChangeLabel); - getMergerRegistry().getHighestRankingMerger(node).copyLeftToRight(node, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(node), new BasicMonitor()); // ** MERGE CHECKING ** comparison = buildComparison(left, right); diff --git a/plugins/org.eclipse.emf.compare.diagram/src/org/eclipse/emf/compare/diagram/internal/merge/AdditiveCompareDiagramMerger.java b/plugins/org.eclipse.emf.compare.diagram/src/org/eclipse/emf/compare/diagram/internal/merge/AdditiveCompareDiagramMerger.java index 51b236a17..b52e9c395 100644 --- a/plugins/org.eclipse.emf.compare.diagram/src/org/eclipse/emf/compare/diagram/internal/merge/AdditiveCompareDiagramMerger.java +++ b/plugins/org.eclipse.emf.compare.diagram/src/org/eclipse/emf/compare/diagram/internal/merge/AdditiveCompareDiagramMerger.java @@ -14,7 +14,8 @@ 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.DifferenceState.MERGED; -import static org.eclipse.emf.compare.DifferenceState.UNRESOLVED; + +import java.util.Set; import org.eclipse.emf.common.util.Monitor; import org.eclipse.emf.compare.Diff; @@ -45,7 +46,7 @@ public class AdditiveCompareDiagramMerger extends CompareDiagramMerger { @Override public void copyRightToLeft(Diff target, Monitor monitor) { - if (target.getState() != UNRESOLVED) { + if (isInTerminalState(target)) { return; } @@ -61,4 +62,25 @@ public class AdditiveCompareDiagramMerger extends CompareDiagramMerger { } } + @Override + public Set<Diff> getDirectMergeDependencies(Diff target, boolean mergeRightToLeft) { + if (target.getSource() == RIGHT && target.getKind() != DELETE) { + return super.getDirectMergeDependencies(target, mergeRightToLeft); + } else if (target.getSource() == LEFT && target.getKind() == DELETE) { + return super.getDirectMergeDependencies(target, mergeRightToLeft); + } else { + return super.getDirectMergeDependencies(target, !mergeRightToLeft); + } + } + + @Override + public Set<Diff> getDirectResultingMerges(Diff target, boolean mergeRightToLeft) { + if (target.getSource() == RIGHT && target.getKind() != DELETE) { + return super.getDirectResultingMerges(target, mergeRightToLeft); + } else if (target.getSource() == LEFT && target.getKind() == DELETE) { + return super.getDirectResultingMerges(target, mergeRightToLeft); + } else { + return super.getDirectResultingMerges(target, !mergeRightToLeft); + } + } } diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.compare.ide.ui.tests/META-INF/MANIFEST.MF index 04cc06a67..1e0025219 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui.tests/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/META-INF/MANIFEST.MF @@ -24,7 +24,8 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.emf.compare.rcp.ui, org.mockito;bundle-version="[1.9.0,2.0.0)", org.hamcrest;bundle-version="[1.1.0,2.0.0)", - org.eclipse.core.filesystem + org.eclipse.core.filesystem, + org.eclipse.emf.compare.ide.ui.tests.framework;bundle-version="[1.0.0,2.0.0)" Bundle-Activator: org.eclipse.emf.compare.ide.ui.tests.Activator Import-Package: com.google.common.base;version="[11.0.0,16.0.0)", com.google.common.collect;version="[11.0.0,16.0.0)", diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/CascadingFilterRefinementTest.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/CascadingFilterRefinementTest.java new file mode 100644 index 000000000..a52055198 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/CascadingFilterRefinementTest.java @@ -0,0 +1,183 @@ +/******************************************************************************* + * 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: + * Martin Fleck - initial API and implementation + *******************************************************************************/ +package org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions; + +import static com.google.common.collect.Iterables.all; +import static com.google.common.collect.Iterables.any; +import static org.eclipse.emf.compare.ConflictKind.REAL; +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.assertTrue; + +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; + +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.eclipse.emf.compare.Comparison; +import org.eclipse.emf.compare.Conflict; +import org.eclipse.emf.compare.Diff; +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.MergeDependenciesUtil; +import org.eclipse.emf.compare.merge.IMergeOptionAware; +import org.eclipse.emf.compare.merge.IMerger; +import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin; +import org.junit.runner.RunWith; + +/** + * This class tests the influence of the cascading differences filter on the merging of refinement + * differences. The expectation is that refining and refined differences can only be merged together, + * independent of the filter setting. + * + * @author Martin Fleck <mfleck@eclipsesource.com> + */ +@SuppressWarnings({"restriction", "nls" }) +@RunWith(RuntimeTestRunner.class) +public class CascadingFilterRefinementTest { + + private static final boolean MERGE_RIGHT_TO_LEFT = true; + + private static final Map<IMergeOptionAware, Object> CACHED_SUBDIFF_OPTIONS = Maps.newHashMap(); + + private static final IMerger.Registry MERGER_REGISTRY = EMFCompareRCPPlugin.getDefault() + .getMergerRegistry(); + + public void enableCascadingFilter() { + setCascadingFilter(true); + } + + public void disableCascadingFilter() { + setCascadingFilter(false); + } + + public 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_SUBDIFF_OPTIONS.put(merger, previousValue); + mergeOptions.put(SUB_DIFF_AWARE_OPTION, Boolean.valueOf(enabled)); + } + } + + public void restoreCascadingFilter() { + // restore previous values + for (Entry<IMergeOptionAware, Object> entry : CACHED_SUBDIFF_OPTIONS.entrySet()) { + IMergeOptionAware merger = entry.getKey(); + merger.getMergeOptions().put(SUB_DIFF_AWARE_OPTION, entry.getValue()); + } + } + + /** + * <p> + * Tests whether refining/refined diffs are only merged together when the cascading filter is enabled. + * Input model: + * </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' subclassing class 'Class1' + * (class 'Class2' and generalization added) + * </ul> + * <p> + * In the comparison, we detect a conflict between adding the generalization and the deletion of class + * 'Class1'. The generalization (DirectRelationshipChange) is a refinement of adding the generalization to + * 'Class2' and setting the generalizations 'general' property to the super class 'Class1'. + * </p> + * + * @see #testRefinement_NoCascadingFilter(Comparison, CompareTestSupport) + */ + @Compare(left = "data/filter/cascading/left.uml", right = "data/filter/cascading/right.uml", ancestor = "data/filter/cascading/ancestor.uml") + public void testRefinement_CascadingFilterEnabled(final Comparison comparison) { + try { + final List<Diff> differences = comparison.getDifferences(); + final List<Conflict> conflicts = comparison.getConflicts(); + + // has real conflict + assertTrue(any(conflicts, containsConflictOfTypes(REAL))); + + // all differences are unresolved + assertTrue(all(differences, hasState(UNRESOLVED))); + + // enable filter and check refinement + enableCascadingFilter(); + verifyRefinement(differences, MERGE_RIGHT_TO_LEFT); + } finally { + restoreCascadingFilter(); + } + } + + /** + * <p> + * Tests whether refining/refined diffs are only merged together when the cascading filter is disabled. + * Input model: + * </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' subclassing class 'Class1' + * (class 'Class2' and generalization added) + * </ul> + * <p> + * In the comparison, we detect a conflict between adding the generalization and the deletion of class + * 'Class1'. The generalization (DirectRelationshipChange) is a refinement of adding the generalization to + * 'Class2' and setting the generalizations 'general' property to the super class 'Class1'. + * </p> + * + * @see #testRefinement_NoCascadingFilter(Comparison, CompareTestSupport) + */ + @Compare(left = "data/filter/cascading/left.uml", right = "data/filter/cascading/right.uml", ancestor = "data/filter/cascading/ancestor.uml") + public void testRefinement_CascadingFilterDisabled(final Comparison comparison) { + try { + final List<Diff> differences = comparison.getDifferences(); + final List<Conflict> conflicts = comparison.getConflicts(); + + // has real conflict + assertTrue(any(conflicts, containsConflictOfTypes(REAL))); + + // all differences are unresolved + assertTrue(all(differences, hasState(UNRESOLVED))); + + // enable filter and check refinement + disableCascadingFilter(); + verifyRefinement(differences, MERGE_RIGHT_TO_LEFT); + } finally { + restoreCascadingFilter(); + } + } + + /** + * Verifies that the calculated resulting merges for each difference contain all refined and refining + * differences, i.e., they may only be merged as a group or not at all. + * + * @param differences + * differences to check + * @param mergeRightToLeft + * merge direction + */ + public void verifyRefinement(List<Diff> differences, boolean mergeRightToLeft) { + for (Diff diff : differences) { + Set<Diff> resultingMerges = MergeDependenciesUtil.getAllResultingMerges(diff, MERGER_REGISTRY, + mergeRightToLeft); + assertTrue("Not all refined diffs are in resulting merges.", + resultingMerges.containsAll(diff.getRefines())); + assertTrue("Not all refining diffs are in resulting merges.", + resultingMerges.containsAll(diff.getRefinedBy())); + } + } +} diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeNonConflictingRunnableRefinementTest.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeNonConflictingRunnableRefinementTest.java new file mode 100644 index 000000000..e1877bcad --- /dev/null +++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeNonConflictingRunnableRefinementTest.java @@ -0,0 +1,576 @@ +/******************************************************************************* + * 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: + * Martin Fleck - initial API and implementation + *******************************************************************************/ +package org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions; + +import static java.util.Arrays.asList; +import static org.eclipse.emf.compare.ConflictKind.REAL; +import static org.eclipse.emf.compare.DifferenceSource.LEFT; +import static org.eclipse.emf.compare.DifferenceSource.RIGHT; +import static org.eclipse.emf.compare.DifferenceState.UNRESOLVED; +import static org.eclipse.emf.compare.internal.merge.MergeMode.LEFT_TO_RIGHT; + +import java.util.List; + +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; +import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeNonConflictingRunnable; +import org.eclipse.emf.compare.internal.merge.MergeMode; +import org.eclipse.emf.compare.internal.spec.ComparisonSpec; +import org.eclipse.emf.compare.internal.spec.ConflictSpec; +import org.eclipse.emf.compare.internal.spec.DiffSpec; +import org.eclipse.emf.compare.internal.spec.MatchSpec; +import org.eclipse.emf.compare.merge.AbstractMerger; +import org.eclipse.emf.compare.merge.IMerger; +import org.junit.Assert; +import org.junit.Test; + +/** + * Tests for ensuring that refinement diffs are only merged together as a whole or not at all when merging + * non-conflicting changes. + * + * @author Martin Fleck <mfleck@eclipsesource.com> + */ +@SuppressWarnings({"restriction", "nls" }) +public class MergeNonConflictingRunnableRefinementTest { + private static final IMerger.Registry MERGER_REGISTRY = IMerger.RegistryImpl.createStandaloneInstance(); + static { + MERGER_REGISTRY.add(new AbstractMerger() { + public boolean isMergerFor(Diff target) { + return true; + } + }); + } + + /** + * Creates a new difference. + * + * @param name + * name used in {@link #toString()} for convenience. + * @param source + * difference source. + * @return newly created difference + */ + protected Diff createDiff(final String name, DifferenceSource source) { + Diff diff = new DiffSpec() { + @Override + public String toString() { + return name; + } + }; + diff.setSource(source); + return diff; + } + + /** + * Creates a new conflict. + * + * @param kind + * conflict kind. + * @param diffs + * differences that participate in the conflict. + * @return newly created conflict + */ + protected Conflict createConflict(ConflictKind kind, Diff... diffs) { + Conflict conflict = new ConflictSpec(); + conflict.setKind(kind); + conflict.getDifferences().addAll(asList(diffs)); + return conflict; + } + + /** + * Creates a new comparison with a single match that holds all differences. + * + * @param differences + * differences in the comparison + * @param conflicts + * conflicts in the comparison + * @return newly created comparison + */ + protected Comparison createComparison(List<Diff> differences, List<Conflict> conflicts) { + Comparison comparison = new ComparisonSpec(); + Match match = new MatchSpec(); + match.getDifferences().addAll(differences); + comparison.getMatches().add(match); + comparison.getConflicts().addAll(conflicts); + comparison.setThreeWay(false); + return comparison; + } + + /** + * With the following refinement graph. Upper layers are refined by lower layers: + * + * <pre> + * Left | Right + * --------+--------- + * A | A + * / \ | / \ + * B C | B C + * + * Merge: Left To Right + * Real Conflict: Left.B, Right.B + * Expected: No Diffs merged + * Start Diff: Left.B + * </pre> + */ + @Test + public void testMergeNonConflictingWithBStartB() { + final boolean isLeftToRight = true; + final MergeMode mergeMode = LEFT_TO_RIGHT; + + // Create diffs + Diff leftA = createDiff("LeftA", LEFT); + Diff leftB = createDiff("LeftB", LEFT); + Diff leftC = createDiff("LeftC", LEFT); + leftA.getRefines().add(leftB); + leftA.getRefines().add(leftC); + + // Create diffs + Diff rightA = createDiff("RightA", RIGHT); + Diff rightB = createDiff("RightB", RIGHT); + Diff rightC = createDiff("RightC", RIGHT); + rightA.getRefines().add(rightB); + rightA.getRefines().add(rightC); + + // Add conflicts + Conflict conflict = createConflict(REAL, leftB, rightB); + + Comparison comparison = createComparison(asList(leftB, leftC, leftA, rightB, rightC, rightA), + asList(conflict)); + + mergeNonConflictingChanges(comparison, mergeMode, isLeftToRight); + verifyAllUnresolved(comparison.getDifferences()); + } + + /** + * With the following refinement graph. Upper layers are refined by lower layers: + * + * <pre> + * Left | Right + * --------+--------- + * A | A + * / \ | / \ + * B C | B C + * + * Merge: Left To Right + * Real Conflict: Left.B, Right.B + * Expected: No Diffs merged + * Start Diff: Left.C + * </pre> + */ + @Test + public void testMergeNonConflictingWithBStartC() { + final boolean isLeftToRight = true; + final MergeMode mergeMode = LEFT_TO_RIGHT; + + // Create diffs + Diff leftA = createDiff("LeftA", LEFT); + Diff leftB = createDiff("LeftB", LEFT); + Diff leftC = createDiff("LeftC", LEFT); + leftA.getRefines().add(leftB); + leftA.getRefines().add(leftC); + + // Create diffs + Diff rightA = createDiff("RightA", RIGHT); + Diff rightB = createDiff("RightB", RIGHT); + Diff rightC = createDiff("RightC", RIGHT); + rightA.getRefines().add(rightB); + rightA.getRefines().add(rightC); + + // Add conflicts + Conflict conflict = createConflict(REAL, leftB, rightB); + + Comparison comparison = createComparison(asList(leftC, leftB, leftA, rightB, rightC, rightA), + asList(conflict)); + + mergeNonConflictingChanges(comparison, mergeMode, isLeftToRight); + verifyAllUnresolved(comparison.getDifferences()); + } + + /** + * With the following refinement graph. Upper layers are refined by lower layers: + * + * <pre> + * Left | Right + * --------+--------- + * A | A + * / \ | / \ + * B C | B C + * + * Merge: Left To Right + * Real Conflict: Left.B, Right.B + * Expected: No Diffs merged + * Start Diff: Left.A + * </pre> + */ + @Test + public void testMergeNonConflictingWithBStartA() { + final boolean isLeftToRight = true; + final MergeMode mergeMode = LEFT_TO_RIGHT; + + // Create diffs + Diff leftA = createDiff("LeftA", LEFT); + Diff leftB = createDiff("LeftB", LEFT); + Diff leftC = createDiff("LeftC", LEFT); + leftA.getRefines().add(leftB); + leftA.getRefines().add(leftC); + + // Create diffs + Diff rightA = createDiff("RightA", RIGHT); + Diff rightB = createDiff("RightB", RIGHT); + Diff rightC = createDiff("RightC", RIGHT); + rightA.getRefines().add(rightB); + rightA.getRefines().add(rightC); + + // Add conflicts + Conflict conflict = createConflict(REAL, leftB, rightB); + + Comparison comparison = createComparison(asList(leftA, leftC, leftB, rightB, rightC, rightA), + asList(conflict)); + + mergeNonConflictingChanges(comparison, mergeMode, isLeftToRight); + verifyAllUnresolved(comparison.getDifferences()); + } + + /** + * With the following refinement graph. Upper layers are refined by lower layers: + * + * <pre> + * Left | Right + * --------+--------- + * A | A + * / \ | / \ + * B C | B C + * + * Merge: Left To Right + * Real Conflict: Left.A, Right.B + * Expected: No Diffs merged + * Start Diff: Left.B + * </pre> + */ + @Test + public void testMergeNonConflictingWithAStartB() { + final boolean isLeftToRight = true; + final MergeMode mergeMode = LEFT_TO_RIGHT; + + // Create diffs + Diff leftA = createDiff("LeftA", LEFT); + Diff leftB = createDiff("LeftB", LEFT); + Diff leftC = createDiff("LeftC", LEFT); + leftA.getRefines().add(leftB); + leftA.getRefines().add(leftC); + + // Create diffs + Diff rightA = createDiff("RightA", RIGHT); + Diff rightB = createDiff("RightB", RIGHT); + Diff rightC = createDiff("RightC", RIGHT); + rightA.getRefines().add(rightB); + rightA.getRefines().add(rightC); + + // Add conflicts + Conflict conflict = createConflict(REAL, leftA, rightB); + + Comparison comparison = createComparison(asList(leftB, leftC, leftA, rightB, rightC, rightA), + asList(conflict)); + + mergeNonConflictingChanges(comparison, mergeMode, isLeftToRight); + verifyAllUnresolved(comparison.getDifferences()); + } + + /** + * With the following refinement graph. Upper layers are refined by lower layers: + * + * <pre> + * Left | Right + * --------+--------- + * A | A + * / \ | / \ + * B C | B C + * + * Merge: Left To Right + * Real Conflict: Left.A, Right.B + * Expected: No Diffs merged + * Start Diff: Left.C + * </pre> + */ + @Test + public void testMergeNonConflictingWithAStartC() { + final boolean isLeftToRight = true; + final MergeMode mergeMode = LEFT_TO_RIGHT; + + // Create diffs + Diff leftA = createDiff("LeftA", LEFT); + Diff leftB = createDiff("LeftB", LEFT); + Diff leftC = createDiff("LeftC", LEFT); + leftA.getRefines().add(leftB); + leftA.getRefines().add(leftC); + + // Create diffs + Diff rightA = createDiff("RightA", RIGHT); + Diff rightB = createDiff("RightB", RIGHT); + Diff rightC = createDiff("RightC", RIGHT); + rightA.getRefines().add(rightB); + rightA.getRefines().add(rightC); + + // Add conflicts + Conflict conflict = createConflict(REAL, leftA, rightB); + + Comparison comparison = createComparison(asList(leftC, leftB, leftA, rightB, rightC, rightA), + asList(conflict)); + + mergeNonConflictingChanges(comparison, mergeMode, isLeftToRight); + verifyAllUnresolved(comparison.getDifferences()); + } + + /** + * With the following refinement graph. Upper layers are refined by lower layers: + * + * <pre> + * Left | Right + * --------+--------- + * A | A + * / \ | / \ + * B C | B C + * + * Merge: Left To Right + * Real Conflict: Left.A, Right.B + * Expected: No Diffs merged + * Start Diff: Left.A + * </pre> + */ + @Test + public void testMergeNonConflictingWithAStartA() { + final boolean isLeftToRight = true; + final MergeMode mergeMode = LEFT_TO_RIGHT; + + // Create diffs + Diff leftA = createDiff("LeftA", LEFT); + Diff leftB = createDiff("LeftB", LEFT); + Diff leftC = createDiff("LeftC", LEFT); + leftA.getRefines().add(leftB); + leftA.getRefines().add(leftC); + + // Create diffs + Diff rightA = createDiff("RightA", RIGHT); + Diff rightB = createDiff("RightB", RIGHT); + Diff rightC = createDiff("RightC", RIGHT); + rightA.getRefines().add(rightB); + rightA.getRefines().add(rightC); + + // Add conflicts + Conflict conflict = createConflict(REAL, leftA, rightB); + + Comparison comparison = createComparison(asList(leftA, leftC, leftB, rightB, rightC, rightA), + asList(conflict)); + + mergeNonConflictingChanges(comparison, mergeMode, isLeftToRight); + verifyAllUnresolved(comparison.getDifferences()); + } + + /** + * With the following refinement graph. Upper layers are refined by lower layers: + * + * <pre> + * Left | Right + * ----------+----------- + * A | A + * / \ | / \ + * B C | B C + * / \ | + * D E | + * + * Merge: Left To Right + * Real Conflict: Left.C, Right.B + * Expected: No Diffs merged + * Start Diff: Left.E + * </pre> + */ + @Test + public void testMergeNonConflictingTwoTiersWithCStartE() { + final boolean isLeftToRight = true; + final MergeMode mergeMode = LEFT_TO_RIGHT; + + // Create diffs + Diff leftA = createDiff("LeftA", LEFT); + Diff leftB = createDiff("LeftB", LEFT); + Diff leftC = createDiff("LeftC", LEFT); + Diff leftD = createDiff("LeftD", LEFT); + Diff leftE = createDiff("LeftE", LEFT); + leftA.getRefines().add(leftB); + leftA.getRefines().add(leftC); + leftB.getRefines().add(leftD); + leftB.getRefines().add(leftE); + + // Create diffs + Diff rightA = createDiff("RightA", RIGHT); + Diff rightB = createDiff("RightB", RIGHT); + Diff rightC = createDiff("RightC", RIGHT); + rightA.getRefines().add(rightB); + rightA.getRefines().add(rightC); + + // Add conflicts + Conflict conflict = createConflict(REAL, leftC, rightB); + + Comparison comparison = createComparison( + asList(leftE, leftC, leftB, leftA, leftD, rightB, rightC, rightA), asList(conflict)); + + mergeNonConflictingChanges(comparison, mergeMode, isLeftToRight); + verifyAllUnresolved(comparison.getDifferences()); + } + + /** + * With the following refinement graph. Upper layers are refined by lower layers: + * + * <pre> + * Left | Right + * --------------+----------- + * A B | A + * / \ / \ | / \ + * C D E | B C + * + * Merge: Left To Right + * Real Conflict: Left.D, Right.B + * Expected: No Diffs merged + * Start Diff: Left.C + * </pre> + */ + @Test + public void testMergeNonConflictingSharedRefiningWithCStartC() { + final boolean isLeftToRight = true; + final MergeMode mergeMode = LEFT_TO_RIGHT; + + // Create diffs + Diff leftA = createDiff("LeftA", LEFT); + Diff leftB = createDiff("LeftB", LEFT); + Diff leftC = createDiff("LeftC", LEFT); + Diff leftD = createDiff("LeftD", LEFT); + Diff leftE = createDiff("LeftE", LEFT); + leftA.getRefines().add(leftC); + leftA.getRefines().add(leftD); + leftB.getRefines().add(leftD); + leftB.getRefines().add(leftE); + + // Create diffs + Diff rightA = createDiff("RightA", RIGHT); + Diff rightB = createDiff("RightB", RIGHT); + Diff rightC = createDiff("RightC", RIGHT); + rightA.getRefines().add(rightB); + rightA.getRefines().add(rightC); + + // Add conflicts + Conflict conflict = createConflict(REAL, leftD, rightB); + + Comparison comparison = createComparison( + asList(leftC, leftE, leftB, leftA, leftD, rightB, rightC, rightA), asList(conflict)); + + mergeNonConflictingChanges(comparison, mergeMode, isLeftToRight); + verifyAllUnresolved(comparison.getDifferences()); + } + + /** + * With the following refinement graph. Upper layers refine lower layers: + * + * <pre> + * Left | Right + * --------------+----------- + * A B | A + * / \ / \ | / \ + * C D E | B C + * + * Merge: Left To Right + * Real Conflict: Left.D, Right.B + * Expected: No Diffs merged + * Start Diff: Left.A + * </pre> + */ + @Test + public void testMergeNonConflictingSharedRefiningWithCStartA() { + final boolean isLeftToRight = true; + final MergeMode mergeMode = LEFT_TO_RIGHT; + + // Create diffs + Diff leftA = createDiff("LeftA", LEFT); + Diff leftB = createDiff("LeftB", LEFT); + Diff leftC = createDiff("LeftC", LEFT); + Diff leftD = createDiff("LeftD", LEFT); + Diff leftE = createDiff("LeftE", LEFT); + leftA.getRefines().add(leftC); + leftA.getRefines().add(leftD); + leftB.getRefines().add(leftD); + leftB.getRefines().add(leftE); + + // Create diffs + Diff rightA = createDiff("RightA", RIGHT); + Diff rightB = createDiff("RightB", RIGHT); + Diff rightC = createDiff("RightC", RIGHT); + rightA.getRefines().add(rightB); + rightA.getRefines().add(rightC); + + // Add conflicts + Conflict conflict = createConflict(REAL, leftD, rightB); + + Comparison comparison = createComparison( + asList(leftA, leftB, leftE, leftC, leftD, rightB, rightC, rightA), asList(conflict)); + + mergeNonConflictingChanges(comparison, mergeMode, isLeftToRight); + verifyAllUnresolved(comparison.getDifferences()); + } + + /** + * Verifies that all differences are unresolved. + * + * @param diffs + * differences + */ + protected void verifyAllUnresolved(List<Diff> diffs) { + for (Diff diff : diffs) { + Assert.assertSame(UNRESOLVED, diff.getState()); + } + } + + /** + * 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 + */ + + private void mergeNonConflictingChanges(Comparison comparison, MergeMode mergeMode, boolean leftToRight) { + final boolean isLeftEditable; + final boolean isRightEditable; + switch (mergeMode) { + case LEFT_TO_RIGHT: + // fall through + case RIGHT_TO_LEFT: + isLeftEditable = true; + isRightEditable = true; + break; + case ACCEPT: + // fall through + case REJECT: + isLeftEditable = true; + isRightEditable = false; + break; + default: + throw new IllegalArgumentException(); + } + MergeNonConflictingRunnable mergeNonConflicting = new MergeNonConflictingRunnable(isLeftEditable, + isRightEditable, mergeMode); + mergeNonConflicting.merge(comparison, leftToRight, MERGER_REGISTRY); + } +} diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeNonConflictingRunnableTest.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeNonConflictingRunnableTest.java index 6b6e576df..52b617316 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeNonConflictingRunnableTest.java +++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeNonConflictingRunnableTest.java @@ -26,7 +26,10 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.google.common.collect.Iterators; + import java.util.Collection; +import java.util.Iterator; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; @@ -42,10 +45,15 @@ import org.eclipse.emf.compare.Match; import org.eclipse.emf.compare.ReferenceChange; import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeNonConflictingRunnable; import org.eclipse.emf.compare.internal.merge.MergeMode; +import org.eclipse.emf.compare.merge.IMergeCriterion; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.merge.IMerger.Registry; +import org.eclipse.emf.compare.merge.IMerger.Registry2; +import org.eclipse.emf.compare.merge.IMerger2; import org.junit.Before; import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; /** * Tests the {@link MergeNonConflictingRunnable} according to the specification given in @@ -63,9 +71,9 @@ public class MergeNonConflictingRunnableTest { private Comparison comparison; - private Registry mergerRegistry; + private Registry2 mergerRegistry; - private IMerger merger; + private IMerger2 merger; private Diff leftDelete; @@ -78,9 +86,15 @@ public class MergeNonConflictingRunnableTest { @Before public void setupMocks() { comparison = mock(Comparison.class); - mergerRegistry = mock(Registry.class); - merger = mock(IMerger.class); + mergerRegistry = mock(Registry2.class); + merger = mock(IMerger2.class); when(mergerRegistry.getHighestRankingMerger(any(Diff.class))).thenReturn(merger); + when(mergerRegistry.getMergersByRankDescending(any(Diff.class), any(IMergeCriterion.class))) + .thenAnswer(new Answer<Iterator<IMerger>>() { + public Iterator<IMerger> answer(InvocationOnMock invocation) throws Throwable { + return Iterators.<IMerger> singletonIterator(merger); + } + }); } @Test @@ -486,6 +500,8 @@ public class MergeNonConflictingRunnableTest { final ReferenceChange diff = mock(ReferenceChange.class, name); when(diff.getSource()).thenReturn(side); when(diff.getKind()).thenReturn(kind); + when(diff.getRefinedBy()).thenReturn(new BasicEList<Diff>()); + when(diff.getRefines()).thenReturn(new BasicEList<Diff>()); when(diff.getState()).thenReturn(UNRESOLVED); return diff; } diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/TestBug434828.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/TestBug434828.java index 674e3b036..6033837e4 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/TestBug434828.java +++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/TestBug434828.java @@ -11,6 +11,7 @@ package org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions; import java.io.IOException; +import java.util.Arrays; import java.util.Collections; import org.eclipse.emf.common.util.BasicMonitor; @@ -23,6 +24,7 @@ import org.eclipse.emf.compare.EMFCompare; import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeRunnableImpl; import org.eclipse.emf.compare.internal.merge.IMergeData; import org.eclipse.emf.compare.internal.merge.MergeMode; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin; import org.eclipse.emf.compare.scope.DefaultComparisonScope; @@ -150,8 +152,7 @@ public class TestBug434828 { */ @Test public void testAcceptConflictDiffWithConflictingDiffWithRequiredByProg() { - mergerRegistry.getHighestRankingMerger(refChangeDiff).copyLeftToRight(refChangeDiff, - new BasicMonitor()); + new BatchMerger(mergerRegistry).copyAllLeftToRight(Arrays.asList(refChangeDiff), new BasicMonitor()); Assert.assertEquals(DifferenceState.MERGED, refChangeDiff.getState()); Assert.assertEquals(DifferenceState.MERGED, holdingRefDeletionDiff.getState()); diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/TestBug434828_2.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/TestBug434828_2.java index 4e5977b19..9848b44ad 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/TestBug434828_2.java +++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/TestBug434828_2.java @@ -11,6 +11,7 @@ package org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions; import java.io.IOException; +import java.util.Arrays; import java.util.Collections; import org.eclipse.emf.common.util.BasicMonitor; @@ -23,6 +24,7 @@ import org.eclipse.emf.compare.EMFCompare; import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeRunnableImpl; import org.eclipse.emf.compare.internal.merge.IMergeData; import org.eclipse.emf.compare.internal.merge.MergeMode; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin; import org.eclipse.emf.compare.scope.DefaultComparisonScope; @@ -148,8 +150,7 @@ public class TestBug434828_2 { */ @Test public void testAcceptConflictDiffWithConflictingDiffWithRequiredByProg() { - mergerRegistry.getHighestRankingMerger(refChangeDiff).copyRightToLeft(refChangeDiff, - new BasicMonitor()); + new BatchMerger(mergerRegistry).copyAllRightToLeft(Arrays.asList(refChangeDiff), new BasicMonitor()); Assert.assertEquals(DifferenceState.MERGED, refChangeDiff.getState()); Assert.assertEquals(DifferenceState.MERGED, holdingRefDeletionDiff.getState()); diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/TestBug475586.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/TestBug475586.java index 3f8c0693f..1102456a2 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/TestBug475586.java +++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/TestBug475586.java @@ -42,6 +42,7 @@ import org.eclipse.emf.edit.tree.TreeFactory; import org.eclipse.emf.edit.tree.TreeNode; import org.eclipse.jface.viewers.StructuredSelection; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; /** @@ -95,6 +96,9 @@ public class TestBug475586 extends AbstractTestUITreeNodeItemProviderAdapter { } @Test + @Ignore("The cascading filter must not be handled by the mergers.\n" + + "It's the responsibility of the UI to compute a list of diffs 'hidden' by the cascading filter" + + "for a selected diff and to call the BatchMerger to merge all these diffs at the same time.") public void testAcceptWithCascadingFilter() { final MergeMode accept = MergeMode.ACCEPT; final boolean leftEditable = true; diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/data/filter/cascading/ancestor.uml b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/data/filter/cascading/ancestor.uml new file mode 100644 index 000000000..6829615c1 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/data/filter/cascading/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.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/data/filter/cascading/left.uml b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/data/filter/cascading/left.uml new file mode 100644 index 000000000..dd04d3c22 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/data/filter/cascading/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.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/data/filter/cascading/right.uml b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/data/filter/cascading/right.uml new file mode 100644 index 000000000..51e98e25f --- /dev/null +++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/data/filter/cascading/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.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/suite/AllTests.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/suite/AllTests.java index 3b67da0bc..59c6776d5 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/suite/AllTests.java +++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/suite/AllTests.java @@ -10,6 +10,8 @@ * Philip Langer - adds test classes * Stefan Dirix - add EMFModelProviderTest * Alexandra Buzila - SynchronizationModelDiagnosticTest + * Martin Fleck - add CascadingFilterRefinementTest and + * MergeNonConflictingRunnableRefinementTest *******************************************************************************/ package org.eclipse.emf.compare.ide.ui.tests.suite; @@ -31,7 +33,9 @@ import org.eclipse.emf.compare.ide.ui.tests.logical.resolver.ThreadedModelResolv import org.eclipse.emf.compare.ide.ui.tests.logical.resolver.ThreadedModelResolverWithCustomDependencyProviderTest; import org.eclipse.emf.compare.ide.ui.tests.logical.synchronizationmodel.SynchronizationModelDiagnosticTest; import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.NavigatableTest; +import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions.CascadingFilterRefinementTest; import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions.MergeActionTest; +import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions.MergeNonConflictingRunnableRefinementTest; import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions.MergeNonConflictingRunnableTest; import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions.PseudoConflictsMergeActionTest; import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions.TooltipProviderTest; @@ -59,7 +63,8 @@ import junit.textui.TestRunner; MergeAllCommandTests.class, LocalMonitoredProxyCreationListenerTest.class, RemoteMonitoredProxyCreationListenerTest.class, MergeNonConflictingRunnableTest.class, RenameDetectorTest.class, SimilarityComputerTest.class, TooltipProviderTest.class, - SynchronizationModelDiagnosticTest.class }) + SynchronizationModelDiagnosticTest.class, CascadingFilterRefinementTest.class, + MergeNonConflictingRunnableRefinementTest.class }) public class AllTests { /** * Launches the test with the given arguments. diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/AdditiveResourceMappingMerger.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/AdditiveResourceMappingMerger.java index c6c64eb96..92b863ada 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/AdditiveResourceMappingMerger.java +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/AdditiveResourceMappingMerger.java @@ -17,7 +17,9 @@ import static org.eclipse.emf.compare.DifferenceSource.LEFT; import static org.eclipse.emf.compare.DifferenceState.DISCARDED; import static org.eclipse.emf.compare.DifferenceState.MERGED; import static org.eclipse.emf.compare.merge.AbstractMerger.getMergerDelegate; -import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasConflict; +import static org.eclipse.emf.compare.merge.AbstractMerger.isInTerminalState; +import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasDirectOrIndirectConflict; +import static org.eclipse.emf.compare.utils.EMFComparePredicates.isAdditiveConflict; import com.google.common.collect.Sets; import com.google.common.io.ByteStreams; @@ -48,20 +50,19 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.Conflict; import org.eclipse.emf.compare.Diff; -import org.eclipse.emf.compare.DifferenceState; import org.eclipse.emf.compare.EMFCompare; import org.eclipse.emf.compare.EMFCompare.Builder; -import org.eclipse.emf.compare.ReferenceChange; -import org.eclipse.emf.compare.graph.IGraph; -import org.eclipse.emf.compare.graph.PruningIterator; import org.eclipse.emf.compare.ide.IAdditiveResourceMappingMerger; import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIMessages; import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIPlugin; import org.eclipse.emf.compare.ide.ui.logical.IModelMinimizer; import org.eclipse.emf.compare.ide.ui.logical.SynchronizationModel; import org.eclipse.emf.compare.ide.utils.ResourceUtil; -import org.eclipse.emf.compare.internal.merge.MergeDependenciesUtil; +import org.eclipse.emf.compare.internal.utils.DiffUtil; import org.eclipse.emf.compare.merge.AdditiveMergeCriterion; +import org.eclipse.emf.compare.merge.ComputeDiffsToMerge; +import org.eclipse.emf.compare.merge.DelegatingMerger; +import org.eclipse.emf.compare.merge.MergeBlockedByConflictException; import org.eclipse.emf.compare.rcp.internal.extension.impl.EMFCompareBuilderConfigurator; import org.eclipse.emf.compare.scope.IComparisonScope; import org.eclipse.team.core.diff.IDiff; @@ -69,10 +70,6 @@ import org.eclipse.team.core.mapping.IMergeContext; public class AdditiveResourceMappingMerger extends EMFResourceMappingMerger implements IAdditiveResourceMappingMerger { - public AdditiveResourceMappingMerger() { - super(); - } - @Override protected void mergeMapping(ResourceMapping mapping, IMergeContext mergeContext, Set<ResourceMapping> failingMappings, IProgressMonitor monitor) throws CoreException { @@ -111,34 +108,40 @@ public class AdditiveResourceMappingMerger extends EMFResourceMappingMerger impl } private Set<URI> performPreMerge(Comparison comparison, SubMonitor subMonitor) { - final IGraph<Diff> differencesGraph = MergeDependenciesUtil.mapDifferences(comparison, - MERGER_REGISTRY, true, null); - final PruningIterator<Diff> iterator = differencesGraph.breadthFirstIterator(); final Monitor emfMonitor = BasicMonitor.toMonitor(subMonitor); - final Set<URI> conflictingURIs = new LinkedHashSet<URI>(); - - while (iterator.hasNext()) { - final Diff next = iterator.next(); - doMergeForDiff(next, differencesGraph, iterator, emfMonitor, conflictingURIs); + ComputeDiffsToMerge computer = new ComputeDiffsToMerge(true, MERGER_REGISTRY, + AdditiveMergeCriterion.INSTANCE).failOnRealConflictUnless(isAdditiveConflict()); + for (Diff next : comparison.getDifferences()) { + doMergeForDiff(next, computer, emfMonitor, conflictingURIs); } - return conflictingURIs; } - private void doMergeForDiff(final Diff diff, final IGraph<Diff> differencesGraph, - final PruningIterator<Diff> iterator, final Monitor emfMonitor, final Set<URI> conflictingURIs) { - if (diff.getState() != DifferenceState.UNRESOLVED) { + private void doMergeForDiff(final Diff diff, final ComputeDiffsToMerge computer, final Monitor emfMonitor, + final Set<URI> conflictingURIs) { + if (isInTerminalState(diff)) { return; } - if (hasConflict(REAL).apply(diff)) { - if (isInAdditiveConflict(diff)) { - // The diff is part of conflict that can be considered as an additive conflict. + try { + Set<Diff> diffsToMerge = computer.getAllDiffsToMerge(diff); + for (Diff toMerge : diffsToMerge) { + atomicMerge(toMerge, emfMonitor); + } + } catch (MergeBlockedByConflictException e) { + conflictingURIs.addAll(collectConflictingResources(e.getConflictingDiffs().iterator())); + } + } + + private void atomicMerge(final Diff diff, final Monitor emfMonitor) { + if (hasDirectOrIndirectConflict(REAL).apply(diff)) { + if (isOnlyInAdditiveConflicts(diff)) { if (diff.getSource() == LEFT) { if (isRequiredByDeletion(diff)) { // Deletion from left side must be overriden by right changes - getMergerDelegate(diff, MERGER_REGISTRY, AdditiveMergeCriterion.INSTANCE) - .copyRightToLeft(diff, emfMonitor); + DelegatingMerger delegatingMerger = getMergerDelegate(diff, MERGER_REGISTRY, + AdditiveMergeCriterion.INSTANCE); + delegatingMerger.copyRightToLeft(diff, emfMonitor); } else { // other left changes have to be kept. Mark them as merged diff.setState(MERGED); @@ -154,14 +157,12 @@ public class AdditiveResourceMappingMerger extends EMFResourceMappingMerger impl } } } else { - // The diff is part of a real conflict. Mark the resource as conflicting. - iterator.prune(); - conflictingURIs - .addAll(collectConflictingResources(differencesGraph.depthFirstIterator(diff))); + throw new IllegalStateException(); } } else if (isPseudoConflicting(diff)) { EList<Diff> conflictingDiffs = diff.getConflict().getDifferences(); + // FIXME This doesn't seem useful for (Diff conflictingDiff : conflictingDiffs) { conflictingDiff.setState(MERGED); } @@ -248,11 +249,11 @@ public class AdditiveResourceMappingMerger extends EMFResourceMappingMerger impl } /** - * Test if a diff or one of the diff that required this one are delete diffs. + * Test if a diff or one of the diffs that require it are delete diffs. * * @param diff * The given diff - * @return <code>true</code> if the diff or one of the diff that requires this one is a deletion + * @return <code>true</code> if the diff or one of the diff that require it is a deletion */ private boolean isRequiredByDeletion(Diff diff) { if (diff.getKind() == DELETE) { @@ -291,39 +292,30 @@ public class AdditiveResourceMappingMerger extends EMFResourceMappingMerger impl * The given diff * @return <code>true</code> if the diff is part of an additive conflict */ - private boolean isInAdditiveConflict(Diff diff) { - boolean isAdditiveConflict = false; - EList<Diff> leftDifferences = diff.getConflict().getLeftDifferences(); - EList<Diff> rightDifferences = diff.getConflict().getRightDifferences(); - if (inAdditiveConflict(leftDifferences)) { - isAdditiveConflict = true; - } else if (inAdditiveConflict(rightDifferences)) { - isAdditiveConflict = true; + private boolean isOnlyInAdditiveConflicts(Diff diff) { + Set<Conflict> checkedConflicts = new LinkedHashSet<Conflict>(); + Conflict conflict = diff.getConflict(); + boolean result = false; + if (conflict != null && conflict.getKind() == REAL && checkedConflicts.add(conflict)) { + if (isAdditiveConflict().apply(conflict)) { + result = true; + } else { + // Short-circuit as soon as non-additive conflict is found + return false; + } } - - return isAdditiveConflict; - } - - /** - * Test an list of diff representing one side of a conflict to determine if we are in an additive conflict - * configuration. - * - * @param diffs - * A list of diffs from on side of a conflict - * @return <code>true</code> if there is a deletion of a containment reference - */ - private boolean inAdditiveConflict(EList<Diff> diffs) { - boolean isCorrect = false; - for (Diff diff : diffs) { - if (diff instanceof ReferenceChange) { - ReferenceChange rc = (ReferenceChange)diff; - if (rc.getReference().isContainment()) { - isCorrect = true; - break; + Set<Diff> allRefiningDiffs = DiffUtil.getAllRefiningDiffs(diff); + for (Diff refiningDiff : allRefiningDiffs) { + conflict = refiningDiff.getConflict(); + if (conflict != null && conflict.getKind() == REAL && checkedConflicts.add(conflict)) { + if (isAdditiveConflict().apply(conflict)) { + result = true; + } else { + // Short-circuit as soon as non-additive conflict is found + return false; } } } - return isCorrect; + return result; } - } diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/EMFResourceMappingMerger.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/EMFResourceMappingMerger.java index 2edc08095..6839ad350 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/EMFResourceMappingMerger.java +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/EMFResourceMappingMerger.java @@ -12,8 +12,8 @@ *******************************************************************************/ package org.eclipse.emf.compare.ide.ui.internal.logical; +import static com.google.common.base.Predicates.alwaysFalse; import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide; -import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasConflict; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -63,12 +63,9 @@ 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.DifferenceState; import org.eclipse.emf.compare.EMFCompare; import org.eclipse.emf.compare.EMFCompare.Builder; import org.eclipse.emf.compare.Match; -import org.eclipse.emf.compare.graph.IGraph; -import org.eclipse.emf.compare.graph.PruningIterator; import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIMessages; import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIPlugin; import org.eclipse.emf.compare.ide.ui.internal.preferences.EMFCompareUIPreferences; @@ -76,12 +73,12 @@ import org.eclipse.emf.compare.ide.ui.logical.IModelMinimizer; import org.eclipse.emf.compare.ide.ui.logical.SynchronizationModel; import org.eclipse.emf.compare.ide.utils.ResourceUtil; import org.eclipse.emf.compare.ide.utils.StorageTraversal; -import org.eclipse.emf.compare.internal.merge.MergeDependenciesUtil; -import org.eclipse.emf.compare.internal.merge.MergeMode; import org.eclipse.emf.compare.merge.BatchMerger; +import org.eclipse.emf.compare.merge.ComputeDiffsToMerge; import org.eclipse.emf.compare.merge.IBatchMerger; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.merge.IMerger.Registry2; +import org.eclipse.emf.compare.merge.MergeBlockedByConflictException; import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin; import org.eclipse.emf.compare.rcp.internal.extension.impl.EMFCompareBuilderConfigurator; import org.eclipse.emf.compare.scope.IComparisonScope; @@ -324,26 +321,30 @@ public class EMFResourceMappingMerger implements IResourceMappingMerger { } private Set<URI> performPreMerge(Comparison comparison, boolean preMerge, SubMonitor subMonitor) { - final IGraph<Diff> differencesGraph = MergeDependenciesUtil.mapDifferences(comparison, - MERGER_REGISTRY, true, MergeMode.RIGHT_TO_LEFT); - final PruningIterator<Diff> iterator = differencesGraph.breadthFirstIterator(); final Monitor emfMonitor = BasicMonitor.toMonitor(subMonitor); - final Set<URI> conflictingURIs = new LinkedHashSet<URI>(); - while (iterator.hasNext()) { - final Diff next = iterator.next(); - if (hasConflict(ConflictKind.REAL).apply(next)) { - iterator.prune(); - conflictingURIs - .addAll(collectConflictingResources(differencesGraph.depthFirstIterator(next))); - } else if (next.getState() != DifferenceState.MERGED && preMerge) { - final IMerger merger = MERGER_REGISTRY.getHighestRankingMerger(next); - merger.copyRightToLeft(next, emfMonitor); - } + for (Diff next : comparison.getDifferences()) { + doMergeForDiff(preMerge, emfMonitor, conflictingURIs, next); } return conflictingURIs; } + protected void doMergeForDiff(boolean preMerge, Monitor emfMonitor, Set<URI> conflictingURIs, Diff diff) { + ComputeDiffsToMerge computer = new ComputeDiffsToMerge(true, MERGER_REGISTRY) + .failOnRealConflictUnless(alwaysFalse()); + try { + Set<Diff> diffsToMerge = computer.getAllDiffsToMerge(diff); + if (preMerge) { + for (Diff toMerge : diffsToMerge) { + final IMerger merger = MERGER_REGISTRY.getHighestRankingMerger(toMerge); + merger.copyRightToLeft(toMerge, emfMonitor); + } + } + } catch (MergeBlockedByConflictException e) { + conflictingURIs.addAll(collectConflictingResources(e.getConflictingDiffs().iterator())); + } + } + /** * Iterates over the given diffs to collect the resources they impact. This will be called in case of * conflicts in order to know exactly which resources should be marked as conflicting. diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/DependencyData.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/DependencyData.java index e2043b1e8..cbceeafe2 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/DependencyData.java +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/DependencyData.java @@ -74,6 +74,7 @@ public class DependencyData { rejectedDiffs.addAll( MergeDependenciesUtil.getAllResultingRejections(diff, mergerRegistry, !leftToRight)); rejectedDiffs.remove(diff); + requires.removeAll(rejectedDiffs); } } } diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/AbstractMergeRunnable.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/AbstractMergeRunnable.java index 24379f214..851d36395 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/AbstractMergeRunnable.java +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/AbstractMergeRunnable.java @@ -10,6 +10,8 @@ *******************************************************************************/ package org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions; +import com.google.common.collect.Sets; + import java.util.Collection; import java.util.Set; @@ -84,7 +86,7 @@ public abstract class AbstractMergeRunnable { } /** - * Marks a single diff as merged, keeping track of the merged mode used for the operation. + * Marks a single diff as merged, keeping track of the merge mode used for the operation. * * @param diff * Diff to mark as merged. @@ -103,13 +105,13 @@ public abstract class AbstractMergeRunnable { final Set<Diff> implied = MergeDependenciesUtil.getAllResultingMerges(diff, mergerRegistry, mergeRightToLeft); - for (Diff impliedDiff : implied) { + final Set<Diff> rejections = MergeDependenciesUtil.getAllResultingRejections(diff, mergerRegistry, + mergeRightToLeft); + for (Diff impliedDiff : Sets.difference(implied, rejections)) { impliedDiff.setState(DifferenceState.MERGED); addOrUpdateMergeData(impliedDiff, mode); } - final Set<Diff> rejections = MergeDependenciesUtil.getAllResultingRejections(diff, mergerRegistry, - mergeRightToLeft); for (Diff impliedRejection : rejections) { impliedRejection.setState(DifferenceState.MERGED); if (mergeMode == MergeMode.LEFT_TO_RIGHT || mergeMode == MergeMode.RIGHT_TO_LEFT) { diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeNonConflictingRunnable.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeNonConflictingRunnable.java index 7dc6d02bd..640982da7 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeNonConflictingRunnable.java +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeNonConflictingRunnable.java @@ -8,16 +8,28 @@ * Contributors: * Obeo - initial API and implementation * Philip Langer - bug 469355, bug 462884, refactorings + * Martin Fleck - bug 507177 *******************************************************************************/ package org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions; import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Predicates.alwaysFalse; import static com.google.common.collect.Iterables.any; import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Sets.newHashSet; +import static org.eclipse.emf.compare.DifferenceSource.LEFT; +import static org.eclipse.emf.compare.DifferenceSource.RIGHT; +import static org.eclipse.emf.compare.internal.merge.MergeMode.ACCEPT; +import static org.eclipse.emf.compare.internal.merge.MergeMode.LEFT_TO_RIGHT; +import static org.eclipse.emf.compare.internal.merge.MergeMode.REJECT; +import static org.eclipse.emf.compare.internal.merge.MergeMode.RIGHT_TO_LEFT; +import static org.eclipse.emf.compare.internal.merge.MergeOperation.MARK_AS_MERGE; +import static org.eclipse.emf.compare.merge.AbstractMerger.isInTerminalState; import static org.eclipse.emf.compare.utils.EMFComparePredicates.containsConflictOfTypes; import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide; -import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasConflict; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -34,20 +46,20 @@ import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.ConflictKind; import org.eclipse.emf.compare.Diff; import org.eclipse.emf.compare.DifferenceSource; -import org.eclipse.emf.compare.DifferenceState; import org.eclipse.emf.compare.domain.IMergeRunnable; -import org.eclipse.emf.compare.graph.IGraph; -import org.eclipse.emf.compare.graph.PruningIterator; import org.eclipse.emf.compare.internal.domain.IMergeAllNonConflictingRunnable; import org.eclipse.emf.compare.internal.merge.MergeDependenciesUtil; import org.eclipse.emf.compare.internal.merge.MergeMode; import org.eclipse.emf.compare.internal.merge.MergeOperation; import org.eclipse.emf.compare.internal.utils.ComparisonUtil; import org.eclipse.emf.compare.merge.BatchMerger; +import org.eclipse.emf.compare.merge.ComputeDiffsToMerge; import org.eclipse.emf.compare.merge.IBatchMerger; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.merge.IMerger.Registry; +import org.eclipse.emf.compare.merge.IMerger.Registry2; import org.eclipse.emf.compare.merge.IMerger2; +import org.eclipse.emf.compare.merge.MergeBlockedByConflictException; /** * Implements the "merge non-conflicting" and "merge all non-conflicting" action. @@ -221,55 +233,73 @@ public class MergeNonConflictingRunnable extends AbstractMergeRunnable implement * @param leftToRight * The direction in which {@code differences} should be merged. * @param mergerRegistry - * The registry of mergers. + * The registry of mergers, must be an instance of Registry2. * @return an iterable over the differences that have actually been merged by this operation. */ private Iterable<Diff> mergeWithConflicts(Collection<Diff> differences, boolean leftToRight, Registry mergerRegistry) { final List<Diff> affectedDiffs = new ArrayList<Diff>(); final Monitor emfMonitor = new BasicMonitor(); - final IGraph<Diff> differencesGraph = MergeDependenciesUtil.mapDifferences(differences, - mergerRegistry, !leftToRight, getMergeMode()); - final PruningIterator<Diff> iterator = differencesGraph.breadthFirstIterator(); + ComputeDiffsToMerge computer = new ComputeDiffsToMerge(!leftToRight, (Registry2)mergerRegistry) + .failOnRealConflictUnless(alwaysFalse()); + final Predicate<? super Diff> filter; + if (getMergeMode() == RIGHT_TO_LEFT) { + filter = fromSide(RIGHT); + } else if (getMergeMode() == LEFT_TO_RIGHT) { + filter = fromSide(LEFT); + } else { + filter = Predicates.alwaysTrue(); + } + Set<Diff> conflictingDiffs = newHashSet(); + for (Diff diff : Iterables.filter(differences, filter)) { + if (!conflictingDiffs.contains(diff)) { + try { + Set<Diff> diffsToMerge = computer.getAllDiffsToMerge(diff); + for (Diff toMerge : diffsToMerge) { + doMergeDiffWithConflicts(leftToRight, mergerRegistry, affectedDiffs, emfMonitor, + toMerge); + } + } catch (MergeBlockedByConflictException e) { + conflictingDiffs.addAll(e.getConflictingDiffs()); + } + } + } - while (iterator.hasNext()) { - final Diff next = iterator.next(); - if (hasConflict(ConflictKind.REAL).apply(next)) { - iterator.prune(); - } else { - if (next.getState() != DifferenceState.MERGED) { - affectedDiffs.add(next); - final IMerger merger = mergerRegistry.getHighestRankingMerger(next); + addOrUpdateMergeData(affectedDiffs, getMergeMode()); + return affectedDiffs; + } - if (LOGGER.isDebugEnabled()) { - LOGGER.debug( - "mergeWithConflicts(Collection<Diff>, boolean, Registry) - Selected merger for diff " //$NON-NLS-1$ - + next.hashCode() + ": " + merger.getClass().getSimpleName()); //$NON-NLS-1$ - } + protected void doMergeDiffWithConflicts(boolean leftToRight, Registry mergerRegistry, + List<Diff> affectedDiffs, Monitor emfMonitor, Diff diff) { + if (!isInTerminalState(diff)) { + affectedDiffs.add(diff); + final IMerger merger = mergerRegistry.getHighestRankingMerger(diff); + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug( + "mergeWithConflicts(Collection<Diff>, boolean, Registry) - Selected merger for diff " //$NON-NLS-1$ + + diff.hashCode() + ": " + merger.getClass().getSimpleName()); //$NON-NLS-1$ + } - if (getMergeMode() == MergeMode.LEFT_TO_RIGHT) { - merger.copyLeftToRight(next, emfMonitor); - } else if (getMergeMode() == MergeMode.RIGHT_TO_LEFT) { - merger.copyRightToLeft(next, emfMonitor); - } else if (getMergeMode() == MergeMode.ACCEPT || getMergeMode() == MergeMode.REJECT) { - MergeOperation mergeAction = getMergeOperation(next); - if (mergeAction == MergeOperation.MARK_AS_MERGE) { - markAsMerged(next, getMergeMode(), leftToRight, mergerRegistry); - } else { - if (isLeftEditable() && !leftToRight) { - merger.copyRightToLeft(next, emfMonitor); - } else if (isRightEditable() && leftToRight) { - merger.copyLeftToRight(next, emfMonitor); - } - } - } else { - throw new IllegalStateException(); + if (getMergeMode() == LEFT_TO_RIGHT) { + merger.copyLeftToRight(diff, emfMonitor); + } else if (getMergeMode() == RIGHT_TO_LEFT) { + merger.copyRightToLeft(diff, emfMonitor); + } else if (getMergeMode() == ACCEPT || getMergeMode() == REJECT) { + MergeOperation mergeAction = getMergeOperation(diff); + if (mergeAction == MARK_AS_MERGE) { + markAsMerged(diff, getMergeMode(), leftToRight, mergerRegistry); + } else { + if (isLeftEditable() && !leftToRight) { + merger.copyRightToLeft(diff, emfMonitor); + } else if (isRightEditable() && leftToRight) { + merger.copyLeftToRight(diff, emfMonitor); } } + } else { + throw new IllegalStateException(); } } - addOrUpdateMergeData(affectedDiffs, getMergeMode()); - return affectedDiffs; } /** diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/checkers/MergeDependenciesChecker.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/checkers/MergeDependenciesChecker.java index f59c143b2..872a55dcb 100644 --- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/checkers/MergeDependenciesChecker.java +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/checkers/MergeDependenciesChecker.java @@ -2,6 +2,8 @@ package org.eclipse.emf.compare.tests.checkers; import static org.junit.Assert.assertEquals; +import com.google.common.collect.Sets; + import java.util.Set; import org.eclipse.emf.compare.Diff; @@ -17,9 +19,9 @@ public class MergeDependenciesChecker { private int nbMerges = 0; - private int nbDeletions = 0; + private int nbRejections = 0; - private boolean isFromRight = true; + private boolean rightToLeft = true; private MergeDependenciesChecker() { // Do nothing @@ -41,26 +43,26 @@ public class MergeDependenciesChecker { } public MergeDependenciesChecker rejects(int nbResultingRejections) { - this.nbDeletions = nbResultingRejections; + this.nbRejections = nbResultingRejections; return this; } public MergeDependenciesChecker rightToLeft() { - this.isFromRight = true; + this.rightToLeft = true; return this; } public MergeDependenciesChecker leftToRight() { - this.isFromRight = false; + this.rightToLeft = false; return this; } public void check() { Set<Diff> allResultingMerges = MergeDependenciesUtil.getAllResultingMerges(diff, registry, - this.isFromRight); + this.rightToLeft); Set<Diff> allResultingRejections = MergeDependenciesUtil.getAllResultingRejections(diff, registry, - this.isFromRight); - assertEquals(this.nbMerges, allResultingMerges.size()); - assertEquals(this.nbDeletions, allResultingRejections.size()); + this.rightToLeft); + assertEquals(this.nbMerges, Sets.difference(allResultingMerges, allResultingRejections).size()); + assertEquals(this.nbRejections, allResultingRejections.size()); } } diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/fragmentation/ResourceAttachmentChangeBug492261.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/fragmentation/ResourceAttachmentChangeBug492261.java index 9ae4578a7..3be135c9b 100644 --- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/fragmentation/ResourceAttachmentChangeBug492261.java +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/fragmentation/ResourceAttachmentChangeBug492261.java @@ -17,6 +17,7 @@ import com.google.common.base.Predicates; import com.google.common.collect.Collections2; import java.io.IOException; +import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -27,6 +28,7 @@ import org.eclipse.emf.compare.DifferenceState; import org.eclipse.emf.compare.EMFCompare; import org.eclipse.emf.compare.ReferenceChange; import org.eclipse.emf.compare.ResourceAttachmentChange; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.scope.DefaultComparisonScope; import org.eclipse.emf.compare.scope.IComparisonScope; @@ -40,7 +42,7 @@ public class ResourceAttachmentChangeBug492261 { private final FragmentationInputData input = new FragmentationInputData(); - private final IMerger.Registry mergerRegistry = IMerger.RegistryImpl.createStandaloneInstance(); + private final BatchMerger batchMerger = new BatchMerger(IMerger.RegistryImpl.createStandaloneInstance()); @Test public void testUncontrolRootResourceImplication_1() throws IOException { @@ -172,18 +174,18 @@ public class ResourceAttachmentChangeBug492261 { assertNotNull(innerNode); if (fragmentedOnLeft) { - mergerRegistry.getHighestRankingMerger(rac).copyRightToLeft(rac, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(rac), new BasicMonitor()); } else { - mergerRegistry.getHighestRankingMerger(rac).copyLeftToRight(rac, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(rac), new BasicMonitor()); } assertEquals(DifferenceState.MERGED, rac.getState()); assertEquals(DifferenceState.MERGED, container.getState()); assertEquals(DifferenceState.UNRESOLVED, innerNode.getState()); if (fragmentedOnLeft) { - mergerRegistry.getHighestRankingMerger(innerNode).copyRightToLeft(innerNode, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(innerNode), new BasicMonitor()); } else { - mergerRegistry.getHighestRankingMerger(innerNode).copyLeftToRight(innerNode, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(innerNode), new BasicMonitor()); } assertEquals(DifferenceState.MERGED, rac.getState()); assertEquals(DifferenceState.MERGED, container.getState()); @@ -223,18 +225,18 @@ public class ResourceAttachmentChangeBug492261 { assertNotNull(innerNode); if (fragmentedOnLeft) { - mergerRegistry.getHighestRankingMerger(rac).copyRightToLeft(rac, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(rac), new BasicMonitor()); } else { - mergerRegistry.getHighestRankingMerger(rac).copyLeftToRight(rac, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(rac), new BasicMonitor()); } assertEquals(DifferenceState.MERGED, rac.getState()); assertEquals(DifferenceState.UNRESOLVED, container.getState()); assertEquals(DifferenceState.UNRESOLVED, innerNode.getState()); if (fragmentedOnLeft) { - mergerRegistry.getHighestRankingMerger(container).copyRightToLeft(container, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(container), new BasicMonitor()); } else { - mergerRegistry.getHighestRankingMerger(container).copyLeftToRight(container, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(container), new BasicMonitor()); } assertEquals(DifferenceState.MERGED, rac.getState()); assertEquals(DifferenceState.MERGED, container.getState()); diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/ComplexMergeTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/ComplexMergeTest.java index 0ce16ab85..32824f4fe 100644 --- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/ComplexMergeTest.java +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/ComplexMergeTest.java @@ -37,6 +37,7 @@ import org.eclipse.emf.compare.Diff; import org.eclipse.emf.compare.DifferenceSource; import org.eclipse.emf.compare.EMFCompare; import org.eclipse.emf.compare.Match; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.scope.DefaultComparisonScope; import org.eclipse.emf.compare.scope.IComparisonScope; @@ -220,12 +221,11 @@ public class ComplexMergeTest { } private void copyRightToLeft(Diff diff) { - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + new BatchMerger(mergerRegistry).copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); } private void copyLeftToRight(Diff diff) { - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); - + new BatchMerger(mergerRegistry).copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); } /** diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/ConflictMergeTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/ConflictMergeTest.java index 24704a3b0..9662ce0e2 100644 --- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/ConflictMergeTest.java +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/ConflictMergeTest.java @@ -28,6 +28,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.UnmodifiableIterator; import java.io.IOException; +import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -40,6 +41,7 @@ import org.eclipse.emf.compare.DifferenceKind; import org.eclipse.emf.compare.DifferenceSource; import org.eclipse.emf.compare.DifferenceState; import org.eclipse.emf.compare.EMFCompare; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.scope.DefaultComparisonScope; import org.eclipse.emf.compare.scope.IComparisonScope; @@ -53,6 +55,7 @@ import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EcoreUtil; +import org.junit.Ignore; import org.junit.Test; @SuppressWarnings("nls") @@ -60,7 +63,7 @@ public class ConflictMergeTest { private IndividualDiffInputData input = new IndividualDiffInputData(); - private final IMerger.Registry mergerRegistry = IMerger.RegistryImpl.createStandaloneInstance(); + private final BatchMerger batchMerger = new BatchMerger(IMerger.RegistryImpl.createStandaloneInstance()); @SuppressWarnings("unchecked") @Test @@ -97,8 +100,7 @@ public class ConflictMergeTest { // Merge C[containmentRef1 add] from left side from left to right : C[containmentRef1 add] from right // side will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diffNodeCLeft).copyLeftToRight(diffNodeCLeft, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diffNodeCLeft), new BasicMonitor()); final EObject rightNodeC = getNodeNamed(right, "C"); assertNotNull(rightNodeC); @@ -127,6 +129,7 @@ public class ConflictMergeTest { @SuppressWarnings("unchecked") @Test + @Ignore("Test was already broken although it didn't fail. Fix it and make sure the result of the merge is correct.") public void testLeftAddRightAdd_LtR_2() throws IOException { // Conflict between C[containmentRef1 add] from left side and C[containmentRef1 add] from right side @@ -160,8 +163,7 @@ public class ConflictMergeTest { // Merge C[containmentRef1 add] from right side from left to right : C[containmentRef1 add] from left // side will not be merge - mergerRegistry.getHighestRankingMerger(diffNodeCRight).copyLeftToRight(diffNodeCRight, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diffNodeCRight), new BasicMonitor()); final EObject rightNodeC = getNodeNamed(right, "C"); assertNull(rightNodeC); @@ -190,6 +192,7 @@ public class ConflictMergeTest { @SuppressWarnings("unchecked") @Test + @Ignore("Test was already broken although it didn't fail. Fix it and make sure the result of the merge is correct.") public void testLeftAddRightAdd_RtL_1() throws IOException { // Conflict between C[containmentRef1 add] from left side and C[containmentRef1 add] from right side @@ -223,8 +226,7 @@ public class ConflictMergeTest { // Merge C[containmentRef1 add] from left side from right to left : C[containmentRef1 add] from right // side will not be merge. - mergerRegistry.getHighestRankingMerger(diffNodeCLeft).copyRightToLeft(diffNodeCLeft, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diffNodeCLeft), new BasicMonitor()); final EObject leftNodeC = getNodeNamed(left, "C"); assertNull(leftNodeC); @@ -286,8 +288,7 @@ public class ConflictMergeTest { // Merge C[containmentRef1 add] from right side from right to left : C[containmentRef1 add] from left // side will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diffNodeCRight).copyRightToLeft(diffNodeCRight, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diffNodeCRight), new BasicMonitor()); final EObject leftNodeC = getNodeNamed(left, "C"); assertNotNull(leftNodeC); @@ -332,7 +333,7 @@ public class ConflictMergeTest { // Merge B[eSuperTypes add] from left to right : B[eClassifiers delete] will be merge from left to // right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eSuperTypes"; final EObject rightEClassB = getNodeNamed(right, "B"); @@ -364,7 +365,7 @@ public class ConflictMergeTest { final Diff diff = Iterators.find(differences.iterator(), fromSide(DifferenceSource.RIGHT)); // Merge B[eClassifiers delete] from left to right : B[eSuperTypes add] will not be merge. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eSuperTypes"; final EObject rightEClassB = getNodeNamed(right, "B"); @@ -403,7 +404,7 @@ public class ConflictMergeTest { final Diff diffB = Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), addedToAttribute("root.origin", featureName, NodeEnum.B))); - mergerRegistry.getHighestRankingMerger(diffA).copyLeftToRight(diffA, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diffA), new BasicMonitor()); final EObject rightElement = getNodeNamed(right, "origin"); assertNotNull(rightElement); @@ -413,7 +414,7 @@ public class ConflictMergeTest { assertTrue(featureValue instanceof Collection<?>); assertTrue(((Collection<?>)featureValue).containsAll(Lists.newArrayList(NodeEnum.A))); - mergerRegistry.getHighestRankingMerger(diffB).copyLeftToRight(diffB, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diffB), new BasicMonitor()); featureValue = rightElement.eGet(feature); assertTrue(featureValue instanceof Collection<?>); @@ -436,7 +437,7 @@ public class ConflictMergeTest { final Diff diffDelete = Iterators.find(differences.iterator(), fromSide(DifferenceSource.RIGHT)); - mergerRegistry.getHighestRankingMerger(diffDelete).copyRightToLeft(diffDelete, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diffDelete), new BasicMonitor()); final EObject rightElement = getNodeNamed(left, "origin"); assertNull(rightElement); @@ -461,7 +462,7 @@ public class ConflictMergeTest { final Diff diff = Iterators.find(differences.iterator(), fromSide(DifferenceSource.LEFT)); // Merge B[eSuperTypes add] from right to left : B[eClassifiers delete] will not be merge - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eSuperTypes"; final EObject leftEClassB = getNodeNamed(left, "B"); @@ -500,7 +501,7 @@ public class ConflictMergeTest { // Merge B[eClassifiers delete] from right to left : B[eSuperTypes add] will be merge from right to // left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eSuperTypes"; final EObject leftEClassB = getNodeNamed(left, "B"); @@ -533,7 +534,7 @@ public class ConflictMergeTest { // Merge B[eClassifiers delete] from left to right : B[eSuperTypes add] will be merge from left to // right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eSuperTypes"; final EObject rightEClassB = getNodeNamed(right, "B"); @@ -565,7 +566,7 @@ public class ConflictMergeTest { final Diff diff = Iterators.find(differences.iterator(), fromSide(DifferenceSource.RIGHT)); // Merge B[eSuperTypes add] from left to right : B[eClassifiers delete] will not be merge. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eSuperTypes"; final EObject rightEClassB = getNodeNamed(right, "B"); @@ -603,7 +604,7 @@ public class ConflictMergeTest { final Diff diff = Iterators.find(differences.iterator(), fromSide(DifferenceSource.LEFT)); // Merge B[eClassifiers delete] from right to left : B[eSuperTypes add] will not be merge. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eSuperTypes"; final EObject leftEClassB = getNodeNamed(left, "B"); @@ -642,7 +643,7 @@ public class ConflictMergeTest { // Merge B[eSuperTypes add] from right to left : B[eClassifiers delete] will be merge from right to // left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eSuperTypes"; final EObject leftEClassB = getNodeNamed(left, "B"); @@ -676,7 +677,7 @@ public class ConflictMergeTest { // Merge A[eClassifiers delete] from left to right : true[abstract set]/true[interface set] will be // merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final EObject rightEClassA = getNodeNamed(right, "A"); assertNull(rightEClassA); @@ -705,7 +706,7 @@ public class ConflictMergeTest { // Merge true[abstract set]/true[interface set] from left to right : A[eClassifiers delete] will not // be merge. Diff abstract_ = diffs.next(); - mergerRegistry.getHighestRankingMerger(abstract_).copyLeftToRight(abstract_, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(abstract_), new BasicMonitor()); final EObject rightEClassA = getNodeNamed(right, "A"); assertNotNull(rightEClassA); @@ -713,7 +714,7 @@ public class ConflictMergeTest { assertTrue(((EClass)rightEClassA).isInterface()); Diff interface_ = diffs.next(); - mergerRegistry.getHighestRankingMerger(interface_).copyLeftToRight(interface_, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(interface_), new BasicMonitor()); assertNotNull(rightEClassA); assertFalse(((EClass)rightEClassA).isAbstract()); @@ -747,7 +748,7 @@ public class ConflictMergeTest { // Merge A[eClassifiers delete] from right to left : true[abstract set]/true[interface set] will not // be merge. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final EObject leftEClassA = getNodeNamed(left, "A"); assertNotNull(leftEClassA); @@ -784,7 +785,7 @@ public class ConflictMergeTest { // Merge true[abstract set]/true[interface set] from right to left : A[eClassifiers delete] will be // merge from right to left too. Diff abstract_ = diffs.next(); - mergerRegistry.getHighestRankingMerger(abstract_).copyRightToLeft(abstract_, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(abstract_), new BasicMonitor()); final EObject leftEClassA = getNodeNamed(left, "A"); assertNotNull(leftEClassA); @@ -792,7 +793,7 @@ public class ConflictMergeTest { assertFalse(((EClass)leftEClassA).isInterface()); Diff interface_ = diffs.next(); - mergerRegistry.getHighestRankingMerger(interface_).copyRightToLeft(interface_, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(interface_), new BasicMonitor()); assertNotNull(leftEClassA); assertTrue(((EClass)leftEClassA).isAbstract()); @@ -822,7 +823,7 @@ public class ConflictMergeTest { // Merge true[abstract set]/true[interface set] from left to right : A[eClassifiers delete] will be // merge from left to right too. Diff abstract_ = diffs.next(); - mergerRegistry.getHighestRankingMerger(abstract_).copyLeftToRight(abstract_, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(abstract_), new BasicMonitor()); final EObject rightEClassA = getNodeNamed(right, "A"); assertNotNull(rightEClassA); @@ -830,7 +831,7 @@ public class ConflictMergeTest { assertFalse(((EClass)rightEClassA).isInterface()); Diff interface_ = diffs.next(); - mergerRegistry.getHighestRankingMerger(interface_).copyLeftToRight(interface_, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(interface_), new BasicMonitor()); assertNotNull(rightEClassA); assertTrue(((EClass)rightEClassA).isAbstract()); @@ -858,7 +859,7 @@ public class ConflictMergeTest { // Merge A[eClassifiers delete] from left to right : true[abstract set]/true[interface set] will not // be merge. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final EObject rightEClassA = getNodeNamed(right, "A"); assertNotNull(rightEClassA); @@ -895,7 +896,7 @@ public class ConflictMergeTest { // Merge true[abstract set]/true[interface set] from right to left : A[eClassifiers delete] will not // be merge. Diff abstract_ = diffs.next(); - mergerRegistry.getHighestRankingMerger(abstract_).copyRightToLeft(abstract_, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(abstract_), new BasicMonitor()); final EObject leftEClassA = getNodeNamed(left, "A"); assertNotNull(leftEClassA); @@ -903,7 +904,7 @@ public class ConflictMergeTest { assertTrue(((EClass)leftEClassA).isInterface()); Diff interface_ = diffs.next(); - mergerRegistry.getHighestRankingMerger(interface_).copyRightToLeft(interface_, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(interface_), new BasicMonitor()); assertNotNull(leftEClassA); assertFalse(((EClass)leftEClassA).isAbstract()); @@ -937,7 +938,7 @@ public class ConflictMergeTest { // Merge A[eClassifiers delete] from right to left : true[abstract set]/true[interface set] will be // merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final EObject leftEClassA = getNodeNamed(left, "A"); assertNull(leftEClassA); @@ -964,7 +965,7 @@ public class ConflictMergeTest { // Merge EBoolean[boolean] [eType set] from left to right : EString[java.lang.String] [eType unset] // will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eType"; final EObject rightEAttributeName = getNodeNamed(right, "name"); @@ -997,7 +998,7 @@ public class ConflictMergeTest { // Merge EString[java.lang.String] [eType unset] from left to right : EBoolean[boolean] [eType set] // will not be merge. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eType"; final EObject rightEAttributeName = getNodeNamed(right, "name"); @@ -1036,7 +1037,7 @@ public class ConflictMergeTest { // Merge EBoolean[boolean] [eType set] from right to left : EString[java.lang.String] [eType unset] // will not be merge. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eType"; final EObject leftEAttributeName = getNodeNamed(left, "name"); @@ -1075,7 +1076,7 @@ public class ConflictMergeTest { // Merge EString[java.lang.String] [eType unset] from right to left : EBoolean[boolean] [eType set] // will also be merged - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eType"; final EObject leftEAttributeName = getNodeNamed(left, "name"); @@ -1107,7 +1108,7 @@ public class ConflictMergeTest { // Merge EString[java.lang.String] [eType unset] from left to right : EBoolean[boolean] [eType set] // will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eType"; final EObject rightEAttributeName = getNodeNamed(right, "name"); @@ -1139,7 +1140,7 @@ public class ConflictMergeTest { // Merge EBoolean[boolean] [eType set] from left to right : EString[java.lang.String] [eType unset] // will not be merge. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eType"; final EObject rightEAttributeName = getNodeNamed(right, "name"); @@ -1178,7 +1179,7 @@ public class ConflictMergeTest { // Merge EString[java.lang.String] [eType unset] from right to left : EBoolean[boolean] [eType set] // will not be merge. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eType"; final EObject leftEAttributeName = getNodeNamed(left, "name"); @@ -1217,7 +1218,7 @@ public class ConflictMergeTest { // Merge EBoolean[boolean] [eType set] from right to left : EString[java.lang.String] [eType unset] // will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eType"; final EObject leftEAttributeName = getNodeNamed(left, "name"); @@ -1250,7 +1251,7 @@ public class ConflictMergeTest { // Merge B[eClassifiers delete] from left to right : EString [eStructuralFeatures move] // will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final EObject rightEClassB = getNodeNamed(right, "B"); assertNull(rightEClassB); @@ -1277,7 +1278,7 @@ public class ConflictMergeTest { // Merge EString [eStructuralFeatures move] from left to right : B[eClassifiers delete] // will not be merged - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eStructuralFeatures"; final EObject rightEClassB = getNodeNamed(right, "B"); @@ -1324,7 +1325,7 @@ public class ConflictMergeTest { // Merge B[eClassifiers delete] from right to left : EString [eStructuralFeatures move] // will not be merge. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eStructuralFeatures"; final EObject leftEClassB = getNodeNamed(left, "B"); @@ -1371,7 +1372,7 @@ public class ConflictMergeTest { // Merge EString [eStructuralFeatures move] from right to left : B[eClassifiers delete] // will be merge too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eStructuralFeatures"; final EObject leftEClassB = getNodeNamed(left, "B"); @@ -1416,7 +1417,7 @@ public class ConflictMergeTest { // Merge EString [eStructuralFeatures move] from left to right : B[eClassifiers delete] // will be merge from left to right. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eStructuralFeatures"; final EObject rightEClassB = getNodeNamed(right, "B"); @@ -1462,7 +1463,7 @@ public class ConflictMergeTest { // Merge B[eClassifiers delete] from left to right : EString [eStructuralFeatures move] // will not be merge. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eStructuralFeatures"; final EObject rightEClassB = getNodeNamed(right, "B"); @@ -1514,7 +1515,7 @@ public class ConflictMergeTest { // Merge EString [eStructuralFeatures move] from right to left : B[eClassifiers delete] // will not be merge. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eStructuralFeatures"; final EObject leftEClassB = getNodeNamed(left, "B"); @@ -1566,7 +1567,7 @@ public class ConflictMergeTest { // Merge B[eClassifiers delete] from right to left : EString [eStructuralFeatures move] // will not be merge. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final String featureName = "eStructuralFeatures"; final EObject leftEClassB = getNodeNamed(left, "B"); @@ -1599,7 +1600,7 @@ public class ConflictMergeTest { final Diff diff = Iterators.find(differences.iterator(), fromSide(DifferenceSource.LEFT)); // Merge the left diff should also merge the right diff - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); final String featureName = "singlevalueEEnumAttribute"; final EObject rightNode = getNodeNamed(right, "root"); @@ -1633,7 +1634,7 @@ public class ConflictMergeTest { final Diff diff = Iterators.find(differences.iterator(), fromSide(DifferenceSource.RIGHT)); // Merge the left diff should also merge the right diff - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); final String featureName = "singlevalueEEnumAttribute"; final EObject rightNode = getNodeNamed(right, "root"); diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/FeatureMaps2wayMergeTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/FeatureMaps2wayMergeTest.java index cfaa3e205..f9e5b2a51 100644 --- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/FeatureMaps2wayMergeTest.java +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/FeatureMaps2wayMergeTest.java @@ -25,6 +25,7 @@ import static org.junit.Assert.assertTrue; import com.google.common.collect.Iterators; import java.io.IOException; +import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -36,6 +37,7 @@ import org.eclipse.emf.compare.DifferenceKind; import org.eclipse.emf.compare.EMFCompare; import org.eclipse.emf.compare.FeatureMapChange; import org.eclipse.emf.compare.ReferenceChange; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.scope.DefaultComparisonScope; import org.eclipse.emf.compare.scope.IComparisonScope; @@ -58,7 +60,7 @@ public class FeatureMaps2wayMergeTest { private IndividualDiffInputData input = new IndividualDiffInputData(); - private final IMerger.Registry mergerRegistry = IMerger.RegistryImpl.createStandaloneInstance(); + private final BatchMerger batchMerger = new BatchMerger(IMerger.RegistryImpl.createStandaloneInstance()); @Test public void test2wayContainmentAdd_LtR_1() throws IOException { @@ -78,7 +80,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node1[firstKey add] from left to right : the FeatureMapChange // <firstKey> Node node1 [map add] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -123,7 +125,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map add] from left to right : the ReferenceChange // Node node1[firstKey add] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -168,7 +170,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node1[firstKey add] from right to left : the FeatureMapChange // <firstKey> Node node1 [map add] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still doesn't exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -213,7 +215,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map add] from right to left : the // ReferenceChange Node node1[firstKey add] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still doesn't exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -258,7 +260,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node2[firstKey delete] from left to right : the FeatureMapChange // <firstKey> Node node2 [map delete] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node2 doesn't still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -303,7 +305,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node2 [map delete] from left to right : the // ReferenceChange Node node2[firstKey delete] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node2 doesn't still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -348,7 +350,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node2[firstKey delete] from right to left: the FeatureMapChange // <firstKey> Node node2 [map delete] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in right final EObject rightNode2 = getNodeNamed(right, "node2"); @@ -393,7 +395,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node2[firstKey delete] from right to left: the FeatureMapChange // <firstKey> Node node2 [map delete] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in right final EObject rightNode2 = getNodeNamed(right, "node2"); @@ -439,7 +441,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from left to right : the FeatureMapChange // <firstKey> Node node1 [map entry key change] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -485,7 +487,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map entry key change] from left to right : the // ReferenceChange Node node1[firstKey move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -531,7 +533,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from right to left : the FeatureMapChange // <firstKey> Node node1 [map entry key change] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -577,7 +579,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map entry key change] from left to right : the // ReferenceChange Node node1[firstKey move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -623,7 +625,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from left to right : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -669,7 +671,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from left to right : the // ReferenceChange Node node1[firstKey move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -715,7 +717,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from right to left : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -761,7 +763,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from right to left : the // ReferenceChange Node node1[firstKey move] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -807,7 +809,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from left to right : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -855,7 +857,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from left to right : the // ReferenceChange Node node1[firstKey move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -903,7 +905,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from right to left : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -951,7 +953,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from right to left : the // ReferenceChange Node node1[firstKey move] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -999,7 +1001,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from left to right : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1045,7 +1047,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from left to right : the // ReferenceChange Node node1[firstKey move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1091,7 +1093,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from left to right : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1137,7 +1139,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from left to right : the // ReferenceChange Node node1[firstKey move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1181,7 +1183,7 @@ public class FeatureMaps2wayMergeTest { // reject all -> element a is moved out from a featuremap-containment for (Diff diff : differences) { - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); } // no differences should be left @@ -1204,7 +1206,7 @@ public class FeatureMaps2wayMergeTest { // accept all -> element a is moved into a featuremap-containment for (Diff diff : differences) { - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); } // no differences should be left @@ -1237,10 +1239,8 @@ public class FeatureMaps2wayMergeTest { assertEquals(2, referenceChangeDiff.getEquivalence().getDifferences().size()); // accept both - mergerRegistry.getHighestRankingMerger(featureMapChangeDiff).copyLeftToRight(featureMapChangeDiff, - new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(referenceChangeDiff).copyLeftToRight(referenceChangeDiff, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(featureMapChangeDiff), new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(referenceChangeDiff), new BasicMonitor()); // no differences should be left comparison = EMFCompare.builder().build().compare(scope); @@ -1272,10 +1272,8 @@ public class FeatureMaps2wayMergeTest { assertEquals(2, referenceChangeDiff.getEquivalence().getDifferences().size()); // reject both - mergerRegistry.getHighestRankingMerger(featureMapChangeDiff).copyRightToLeft(featureMapChangeDiff, - new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(referenceChangeDiff).copyRightToLeft(referenceChangeDiff, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(featureMapChangeDiff), new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(referenceChangeDiff), new BasicMonitor()); // no differences should be left comparison = EMFCompare.builder().build().compare(scope); @@ -1301,7 +1299,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node1[firstKey add] from left to right : the FeatureMapChange // <firstKey> Node node1 [map add] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1359,7 +1357,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map add] from left to right : the ReferenceChange // Node node1[firstKey add] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1417,7 +1415,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node1[firstKey add] from right to left : the FeatureMapChange // <firstKey> Node node1 [map add] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1471,7 +1469,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map add] from right to left : the ReferenceChange // Node node1[firstKey add] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1525,7 +1523,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node2[firstKey delete] from left to right : the FeatureMapChange // <firstKey> Node node2 [map delete] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -1579,7 +1577,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node2 [map delete] from left to right : the // ReferenceChange Node node2[firstKey delete] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -1633,7 +1631,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node2[firstKey delete] from right to left : the FeatureMapChange // <firstKey> Node node2 [map delete] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -1691,7 +1689,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node2 [map delete] from right to left : the // ReferenceChange Node node2[firstKey delete] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -1750,7 +1748,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from left to right : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1809,7 +1807,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from left to right : the // ReferenceChange Node node1[firstKey move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1868,7 +1866,7 @@ public class FeatureMaps2wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from right to left : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1927,7 +1925,7 @@ public class FeatureMaps2wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from right to left : the // ReferenceChange Node node1[firstKey move] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/FeatureMaps3wayMergeTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/FeatureMaps3wayMergeTest.java index 9494f585f..d958a40f3 100644 --- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/FeatureMaps3wayMergeTest.java +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/FeatureMaps3wayMergeTest.java @@ -27,6 +27,7 @@ import static org.junit.Assert.assertTrue; import com.google.common.collect.Iterators; import java.io.IOException; +import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -40,6 +41,7 @@ import org.eclipse.emf.compare.DifferenceSource; import org.eclipse.emf.compare.EMFCompare; import org.eclipse.emf.compare.FeatureMapChange; import org.eclipse.emf.compare.ReferenceChange; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.scope.DefaultComparisonScope; import org.eclipse.emf.compare.scope.IComparisonScope; @@ -75,7 +77,7 @@ public class FeatureMaps3wayMergeTest { private IndividualDiffInputData input = new IndividualDiffInputData(); - private final IMerger.Registry mergerRegistry = IMerger.RegistryImpl.createStandaloneInstance(); + private final BatchMerger batchMerger = new BatchMerger(IMerger.RegistryImpl.createStandaloneInstance()); @Test public void test3wayContainmentAdd_Left_LtR_1() throws IOException { @@ -94,7 +96,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1[firstKey add] from left to right : the FeatureMapChange // <firstKey> Node node1 [map add] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -138,7 +140,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node2[firstKey add] from left to right : the FeatureMapChange // <firstKey> Node node2 [map add] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node2 still doesn't exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -182,7 +184,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map add] from left to right : the ReferenceChange // Node node1[firstKey add] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -226,7 +228,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node2 [map add] from left to right : the ReferenceChange // Node node2 [firstKey add] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node2 doesn't still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -270,7 +272,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1[firstKey add] from right to left : the FeatureMapChange // <firstKey> Node node1 [map add] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still doesn't exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -314,7 +316,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node2 [firstKey add] from right to left : the FeatureMapChange // <firstKey> Node node2 [map add] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in right final EObject rightNode2 = getNodeNamed(right, "node2"); @@ -358,7 +360,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map add] from right to left : the // ReferenceChange Node node1[firstKey add] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still doesn't exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -402,7 +404,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node2 [map add] from right to left : the // ReferenceChange Node node2 [firstKey add] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in right final EObject rightNode2 = getNodeNamed(right, "node2"); @@ -446,7 +448,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node2 [firstKey delete] from left to right : the FeatureMapChange // <firstKey> Node node2 [map delete] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node2 doesn't still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -490,7 +492,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1 [firstKey delete] from left to right : the FeatureMapChange // <firstKey> Node node1 [map delete] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -534,7 +536,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node2 [map delete] from left to right : the // ReferenceChange Node node2 [firstKey delete] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node2 doesn't still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -578,7 +580,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node2 [map delete] from left to right : the // ReferenceChange Node node2 [firstKey delete] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -622,7 +624,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node2 [firstKey delete] from right to left: the FeatureMapChange // <firstKey> Node node2 [map delete] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in right final EObject rightNode2 = getNodeNamed(right, "node2"); @@ -666,7 +668,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1 [firstKey delete] from right to left: the FeatureMapChange // <firstKey> Node node1 [map delete] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 doesn't still exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -710,7 +712,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node2 [map delete] from right to left: the // ReferenceChange Node node2 [firstKey delete] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in right final EObject rightNode2 = getNodeNamed(right, "node2"); @@ -754,7 +756,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map delete] from right to left: the // ReferenceChange Node node1 [firstKey delete] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 doesn't still exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -799,7 +801,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from left to right : the FeatureMapChange // <firstKey> Node node1 [map entry key change] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -846,7 +848,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map entry key change] from left to right : the // ReferenceChange Node node1[firstKey move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -891,7 +893,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from right to left : the FeatureMapChange // <firstKey> Node node1 [map entry key change] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -936,7 +938,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map entry key change] from left to right : the // ReferenceChange Node node1[firstKey move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -981,7 +983,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from left to right : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1027,7 +1029,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from left to right : the // ReferenceChange Node node1[firstKey move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1073,7 +1075,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from right to left : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in right final EObject rNode1 = getNodeNamed(right, "node1"); @@ -1118,7 +1120,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from right to left : the // ReferenceChange Node node1[firstKey move] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -1168,10 +1170,8 @@ public class FeatureMaps3wayMergeTest { not(isEquivalentTo(featureMapChangeDiff)))); // accepting -> element a will be moved into a featuremap - mergerRegistry.getHighestRankingMerger(featureMapChangeDiff).copyLeftToRight(featureMapChangeDiff, - new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(referenceChangeDiff).copyLeftToRight(referenceChangeDiff, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(featureMapChangeDiff), new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(referenceChangeDiff), new BasicMonitor()); scope = new DefaultComparisonScope(left, right, null); comparison = EMFCompare.builder().build().compare(scope); @@ -1203,10 +1203,8 @@ public class FeatureMaps3wayMergeTest { not(isEquivalentTo(featureMapChangeDiff)))); // rejecting means that instead of moving inside the element will be moved outside of the featuremap - mergerRegistry.getHighestRankingMerger(featureMapChangeDiff).copyRightToLeft(featureMapChangeDiff, - new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(referenceChangeDiff).copyRightToLeft(referenceChangeDiff, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(featureMapChangeDiff), new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(referenceChangeDiff), new BasicMonitor()); scope = new DefaultComparisonScope(left, origin, null); comparison = EMFCompare.builder().build().compare(scope); @@ -1246,10 +1244,8 @@ public class FeatureMaps3wayMergeTest { assertEquals(2, rightReferenceChangeDiff.getEquivalence().getDifferences().size()); // accept both - mergerRegistry.getHighestRankingMerger(leftFeatureMapChangeDiff) - .copyLeftToRight(leftFeatureMapChangeDiff, new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(leftReferenceChangeDiff) - .copyLeftToRight(leftReferenceChangeDiff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(leftFeatureMapChangeDiff), new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(leftReferenceChangeDiff), new BasicMonitor()); // no differences should be left scope = new DefaultComparisonScope(left, right, null); @@ -1288,10 +1284,8 @@ public class FeatureMaps3wayMergeTest { assertEquals(2, rightReferenceChangeDiff.getEquivalence().getDifferences().size()); // reject both - mergerRegistry.getHighestRankingMerger(leftFeatureMapChangeDiff) - .copyRightToLeft(leftFeatureMapChangeDiff, new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(leftReferenceChangeDiff) - .copyRightToLeft(leftReferenceChangeDiff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(leftFeatureMapChangeDiff), new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(leftReferenceChangeDiff), new BasicMonitor()); // no differences should be left scope = new DefaultComparisonScope(left, right, null); @@ -1317,7 +1311,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1 [firstKey move] from left to right : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1364,7 +1358,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from left to right : the // ReferenceChange Node node1[firstKey move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1411,7 +1405,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from right to left : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -1458,7 +1452,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from right to left : the // ReferenceChange Node node1[firstKey move] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in right final EObject rightNode1 = getNodeNamed(right, "node1"); @@ -1505,7 +1499,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from left to right : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1550,7 +1544,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1[firstKey move] from right to left : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1595,7 +1589,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from right to left : the // ReferenceChange Node node1[firstKey move] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1640,7 +1634,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from left to right : the // ReferenceChange Node node1[firstKey move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1686,7 +1680,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1[firstKey add] from left to right : the FeatureMapChange // <firstKey> Node node1 [map add] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1743,7 +1737,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node2 [firstKey add] from left to right : the FeatureMapChange // <firstKey> Node node2 [map add] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -1798,7 +1792,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map add] from left to right : the ReferenceChange // Node node1[firstKey add] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1855,7 +1849,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map add] from left to right : the ReferenceChange // Node node1[firstKey add] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -1910,7 +1904,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1[firstKey add] from right to left : the FeatureMapChange // <firstKey> Node node1 [map add] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1963,7 +1957,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node2 [firstKey add] from right to left : the FeatureMapChange // <firstKey> Node node2 [map add] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -2020,7 +2014,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map add] from right to left : the ReferenceChange // Node node1[firstKey add] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -2073,7 +2067,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map add] from right to left : the ReferenceChange // Node node1[firstKey add] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -2130,7 +2124,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node2 [firstKey delete] from left to right : the FeatureMapChange // <firstKey> Node node2 [map delete] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -2183,7 +2177,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1 [firstKey delete] from left to right : the FeatureMapChange // <firstKey> Node node1 [map delete] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -2238,7 +2232,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node2 [map delete] from left to right : the // ReferenceChange Node node2 [firstKey delete] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -2291,7 +2285,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map delete] from left to right : the // ReferenceChange Node node1 [firstKey delete] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -2346,7 +2340,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node2 [firstKey delete] from right to left : the FeatureMapChange // <firstKey> Node node2 [map delete] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -2403,7 +2397,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1 [firstKey delete] from right to left : the FeatureMapChange // <firstKey> Node node1 [map delete] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -2456,7 +2450,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node2 [map delete] from right to left : the // ReferenceChange Node node2 [firstKey delete] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node2 still exists in left final EObject leftNode2 = getNodeNamed(left, "node2"); @@ -2513,7 +2507,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node2 [map delete] from right to left : the // ReferenceChange Node node2 [firstKey delete] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -2567,7 +2561,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1 [firstKey move] from left to right : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -2625,7 +2619,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from left to right : the // ReferenceChange Node node1[firstKey move] will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -2683,7 +2677,7 @@ public class FeatureMaps3wayMergeTest { // Merge the ReferenceChange Node node1 [firstKey move] from right to left : the FeatureMapChange // <firstKey> Node node1 [map move] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -2741,7 +2735,7 @@ public class FeatureMaps3wayMergeTest { // Merge the FeatureMapChange <firstKey> Node node1 [map move] from right to left : the // ReferenceChange Node node1[firstKey move] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/FeatureMapsConflictsMergeTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/FeatureMapsConflictsMergeTest.java index 0eaad12c8..c6b19a799 100644 --- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/FeatureMapsConflictsMergeTest.java +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/FeatureMapsConflictsMergeTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertTrue; import com.google.common.collect.Iterators; import java.io.IOException; +import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -34,6 +35,7 @@ import org.eclipse.emf.compare.DifferenceSource; import org.eclipse.emf.compare.EMFCompare; import org.eclipse.emf.compare.FeatureMapChange; import org.eclipse.emf.compare.ReferenceChange; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.scope.DefaultComparisonScope; import org.eclipse.emf.compare.scope.IComparisonScope; @@ -56,7 +58,7 @@ public class FeatureMapsConflictsMergeTest { private IndividualDiffInputData input = new IndividualDiffInputData(); - private final IMerger.Registry mergerRegistry = IMerger.RegistryImpl.createStandaloneInstance(); + private final BatchMerger batchMerger = new BatchMerger(IMerger.RegistryImpl.createStandaloneInstance()); @Test public void testConflictContainmentLeftAddRightAddWithSameKey_LtR_1() throws IOException { @@ -78,7 +80,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left ReferenceChange Node node1 [firstKey add] from left to right : the left // FeatureMapChange <firstKey> Node node1 [map add] will be merge from left to right too. // The rights diffs will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -159,7 +161,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left FeatureMapChange <firstKey> Node node1 [map add] from left to right : the left // ReferenceChange Node node1 [firstKey add] will be merge from left to right too. // The rights diffs will be merge from left to right too. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -240,7 +242,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left ReferenceChange Node node1 [firstKey add] from right to left : the left // FeatureMapChange <firstKey> Node node1 [map add] will be merge from right to left too. // The rights diffs won't be merge from right to left. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 doesn't exists anymore in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -319,7 +321,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left FeatureMapChange <firstKey> Node node1 [map add] from right to left : the left // ReferenceChange Node node1 [firstKey add] will be merge from right to left too. // The rights diffs won't be merge from right to left. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 doesn't exists anymore in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -400,7 +402,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left ReferenceChange Node node1 [firstKey add] from left to right : the left // FeatureMapChange <firstKey> Node node1 [map add] will be merge from left to right too. // The rights diffs will be mark as merged. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -463,7 +465,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left FeatureMapChange <firstKey> Node node1 [map add] from left to right : the left // ReferenceChange Node node1 [firstKey add] will be merge from left to right too. // The rights diffs will be mark as merged. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -525,7 +527,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left ReferenceChange Node node1 [firstKey add] from right to left : the left // FeatureMapChange <firstKey> Node node1 [map add] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 doesn't exists anymore in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -584,7 +586,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left FeatureMapChange <firstKey> Node node1 [map add] from right to left : the left // ReferenceChange Node node1 [firstKey add] will be merge from right to left too. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 doesn't exists anymore in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -642,7 +644,7 @@ public class FeatureMapsConflictsMergeTest { // FeatureMapChange <secondKey> Node node1 [map entry key change] will be merge from left to right // too. // The rights diffs will be mark as merged. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -701,7 +703,7 @@ public class FeatureMapsConflictsMergeTest { // FeatureMapChange <firstKey> Node node1 [map delete] will be merge from left to right // too. // The rights diffs will remains unmerged. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -760,7 +762,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left FeatureMapChange <secondKey> Node node1 [map entry key change] from left to right : // the left ReferenceChange Node node1 [secondKey move] will be merge from left to right too. // The rights diffs will be mark as merged. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -818,7 +820,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the right FeatureMapChange <firstKey> Node node1 [map delete] from left to right : the right // ReferenceChange Node node1 [firstKey delete] will be merge from left to right too. // The rights diffs will remains unmerged. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -878,7 +880,7 @@ public class FeatureMapsConflictsMergeTest { // FeatureMapChange <secondKey> Node node1 [map entry key change] will be merge from right to left // too. // The rights diffs will remains unmerged. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -936,7 +938,7 @@ public class FeatureMapsConflictsMergeTest { // FeatureMapChange <firstKey> Node node1 [map delete] will be merge from right to left // too. // The rights diffs will be mark as merged. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 doesn't exists anymore in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -992,7 +994,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left FeatureMapChange <secondKey> Node node1 [map entry key change] from right to left : // the left ReferenceChange Node node1 [secondKey move] will be merge from right to left too. // The rights diffs will remains unmerged. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1050,7 +1052,7 @@ public class FeatureMapsConflictsMergeTest { // the right ReferenceChange Node node1 [firstKey delete] will be merge from right to left // too. // The rights diffs will be mark as merged. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 doesn't exists anymore in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1107,7 +1109,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left ReferenceChange Node node1 [firstKey add] from left to right : the left // FeatureMapChange <firstKey> Node node1 [map add] will be merge from left to right too. // The rights diffs will be mark as merged. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1166,7 +1168,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left FeatureMapChange <firstKey> Node node1 [map add] from left to right : the left // ReferenceChange Node node1 [firstKey add] will be merge from left to right too. // The rights diffs will be mark as merged. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1225,7 +1227,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left ReferenceChange Node node1 [firstKey add] from right to left : the left // FeatureMapChange <firstKey> Node node1 [map add] will be merge from right to left too. // The rights diffs will remains unmerged. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1284,7 +1286,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left FeatureMapChange <firstKey> Node node1 [map add] from right to left : the left // ReferenceChange Node node1 [firstKey add] will be merge from right to left too. // The rights diffs will remains unmerged. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1344,7 +1346,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left ReferenceChange Node node1 [firstKey move] from left to right : the left // FeatureMapChange <firstKey> Node node1 [map move] will be merge from left to right too. // The rights diffs will be mark as merged. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1406,7 +1408,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left FeatureMapChange <firstKey> Node node1 [map move] from left to right : the left // ReferenceChange Node node1 [firstKey move] will be merge from left to right too. // The rights diffs will be mark as merged. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1468,7 +1470,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left ReferenceChange Node node1 [firstKey move] from right to left : the left // FeatureMapChange <firstKey> Node node1 [map move] will be merge from right to left too. // The rights diffs will remains unmerged. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1530,7 +1532,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left FeatureMapChange <firstKey> Node node1 [map move] from right to left : the left // ReferenceChange Node node1 [firstKey move] will be merge from right to left too. // The rights diffs will remains unmerged. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1595,7 +1597,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left ReferenceChange Node node1 [firstKey move] from left to right : the left // FeatureMapChange <firstKey> Node node1 [map move] will be merge from left to right too. // The rights diffs will be mark as merged. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1660,7 +1662,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left FeatureMapChange <firstKey> Node node1 [map move] from left to right : the left // ReferenceChange Node node1 [firstKey move] will be merge from left to right too. // The rights diffs will be mark as merged. - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1725,7 +1727,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left ReferenceChange Node node1 [firstKey move] from right to left : the left // FeatureMapChange <firstKey> Node node1 [map move] will be merge from right to left too. // The rights diffs will remains unmerged. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); @@ -1790,7 +1792,7 @@ public class FeatureMapsConflictsMergeTest { // Merge the left FeatureMapChange <firstKey> Node node1 [map move] from right to left : the left // ReferenceChange Node node1 [firstKey move] will be merge from right to left too. // The rights diffs will remains unmerged. - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); // node1 still exists in left final EObject leftNode1 = getNodeNamed(left, "node1"); diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/ImplicationsMergeTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/ImplicationsMergeTest.java new file mode 100644 index 000000000..804d55ab5 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/ImplicationsMergeTest.java @@ -0,0 +1,329 @@ +/******************************************************************************* + * 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: + * Martin Fleck - initial API and implementation + *******************************************************************************/ +package org.eclipse.emf.compare.tests.merge; + +import static org.eclipse.emf.compare.DifferenceState.MERGED; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Set; + +import org.eclipse.emf.common.util.BasicMonitor; +import org.eclipse.emf.compare.Diff; +import org.eclipse.emf.compare.internal.spec.DiffSpec; +import org.eclipse.emf.compare.merge.AbstractMerger; +import org.eclipse.emf.compare.merge.BatchMerger; +import org.eclipse.emf.compare.merge.IMerger; +import org.eclipse.emf.compare.merge.IMerger2; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests the implication relationship between differences. In EMF Compare, implication means that we always + * merge the antecedent (A) instead of the consequent (B) in a relationship A implies B. B is considered + * merged if A is merged and therefore requires no merging of its own. + * + * @author <a href="mailto:mfleck@eclipsesource.com">Martin Fleck</a> + */ +public class ImplicationsMergeTest { + private static final boolean MERGE_RIGHT_TO_LEFT = false; + + private final IMerger.Registry mergerRegistry = IMerger.RegistryImpl.createStandaloneInstance(); + + private final BatchMerger batchMerger = new BatchMerger(mergerRegistry); + + @Before + public void setUp() { + mergerRegistry.add(new AbstractMerger() { + public boolean isMergerFor(Diff target) { + return true; + } + }); + } + + protected IMerger2 getMerger(Diff diff) { + return (IMerger2)mergerRegistry.getHighestRankingMerger(diff); + } + + protected void mergeLeftToRight(Diff diff) { + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); + } + + protected Set<Diff> getDirectResultingMerges(Diff diff) { + return getMerger(diff).getDirectResultingMerges(diff, MERGE_RIGHT_TO_LEFT); + } + + /** + * Tests: A => B <br/> + * Merge: A <br/> + * Resulting Merges: A, B <br/> + * A implies B, therefore if we merge A, B is set to MERGED automatically. + */ + @Test + public void testsAImpliesBMergeA() { + Diff diffA = createDiff("DiffA"); //$NON-NLS-1$ + Diff diffB = createDiff("DiffB"); //$NON-NLS-1$ + diffA.getImplies().add(diffB); + + Set<Diff> resultingMerges = getDirectResultingMerges(diffA); + assertEquals(1, resultingMerges.size()); + assertSame(diffB, resultingMerges.iterator().next()); + + resultingMerges = getDirectResultingMerges(diffB); + assertEquals(1, resultingMerges.size()); + assertSame(diffA, resultingMerges.iterator().next()); + + mergeLeftToRight(diffA); + assertEquals(MERGED, diffA.getState()); + assertEquals(MERGED, diffB.getState()); + } + + /** + * Tests: A => B <br/> + * Merge: B <br/> + * Resulting Merges: A, B <br/> + * In EMF Compare, implication means that we always merge the antecedent (A) instead of the consequent + * (B), i.e., B requires no merging. Therefore A is merged and B is set to MERGED automatically. + */ + @Test + public void testsAImpliesBMergeB() { + Diff diffA = createDiff("DiffA"); //$NON-NLS-1$ + Diff diffB = createDiff("DiffB"); //$NON-NLS-1$ + diffA.getImplies().add(diffB); + + Set<Diff> resultingMerges = getDirectResultingMerges(diffA); + assertEquals(1, resultingMerges.size()); + assertSame(diffB, resultingMerges.iterator().next()); + + resultingMerges = getDirectResultingMerges(diffB); + assertEquals(1, resultingMerges.size()); + assertSame(diffA, resultingMerges.iterator().next()); + + mergeLeftToRight(diffB); + assertEquals(MERGED, diffA.getState()); + assertEquals(MERGED, diffB.getState()); + } + + /** + * Tests: A => B, B => C <br/> + * Merge: A <br/> + * Resulting Merges: A, B, C <br/> + * A implies B, therefore if we merge A, B is set to MERGED automatically (requires no merging). Since B + * also implies C, C is also set to MERGED automatically. + */ + @Test + public void testsAImpliesBImpliesCMergeA() { + Diff diffA = createDiff("DiffA"); //$NON-NLS-1$ + Diff diffB = createDiff("DiffB"); //$NON-NLS-1$ + Diff diffC = createDiff("DiffC"); //$NON-NLS-1$ + diffA.getImplies().add(diffB); + diffB.getImplies().add(diffC); + + Set<Diff> resultingMerges = getDirectResultingMerges(diffA); + assertEquals(1, resultingMerges.size()); + assertSame(diffB, resultingMerges.iterator().next()); + + resultingMerges = getDirectResultingMerges(diffB); + assertEquals(2, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffA)); + assertTrue(resultingMerges.contains(diffC)); + + resultingMerges = getDirectResultingMerges(diffC); + assertEquals(1, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffB)); + + mergeLeftToRight(diffA); + assertEquals(MERGED, diffA.getState()); + assertEquals(MERGED, diffB.getState()); + assertEquals(MERGED, diffC.getState()); + } + + /** + * Tests: A => B, B => C <br/> + * Merge: B <br/> + * Resulting Merges: A, B, C <br/> + * In EMF Compare, implication means that we always merge A instead of B (B requires no merging), + * therefore A is merged and B is set to MERGED automatically. B also implies C, so C is also set to + * MERGED automatically. + */ + @Test + public void testsAImpliesBImpliesCMergeB() { + Diff diffA = createDiff("DiffA"); //$NON-NLS-1$ + Diff diffB = createDiff("DiffB"); //$NON-NLS-1$ + Diff diffC = createDiff("DiffC"); //$NON-NLS-1$ + diffA.getImplies().add(diffB); + diffB.getImplies().add(diffC); + + Set<Diff> resultingMerges = getDirectResultingMerges(diffA); + assertEquals(1, resultingMerges.size()); + assertSame(diffB, resultingMerges.iterator().next()); + + resultingMerges = getDirectResultingMerges(diffB); + assertEquals(2, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffA)); + assertTrue(resultingMerges.contains(diffC)); + + resultingMerges = getDirectResultingMerges(diffC); + assertEquals(1, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffB)); + + mergeLeftToRight(diffB); + assertEquals(MERGED, diffA.getState()); + assertEquals(MERGED, diffB.getState()); + assertEquals(MERGED, diffC.getState()); + } + + /** + * Tests: A => B, B => C <br/> + * Merge: C <br/> + * Resulting Merges: A, B, C <br/> + * In EMF Compare, implication means that we always merge A instead of B (B requires no merging), and B + * instead of C. Therefore A is merged and B and C are set to MERGED automatically. + */ + @Test + public void testsAImpliesBImpliesCMergeC() { + Diff diffA = createDiff("DiffA"); //$NON-NLS-1$ + Diff diffB = createDiff("DiffB"); //$NON-NLS-1$ + Diff diffC = createDiff("DiffC"); //$NON-NLS-1$ + diffA.getImplies().add(diffB); + diffB.getImplies().add(diffC); + + Set<Diff> resultingMerges = getDirectResultingMerges(diffA); + assertEquals(1, resultingMerges.size()); + assertSame(diffB, resultingMerges.iterator().next()); + + resultingMerges = getDirectResultingMerges(diffB); + assertEquals(2, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffA)); + assertTrue(resultingMerges.contains(diffC)); + + resultingMerges = getDirectResultingMerges(diffC); + assertEquals(1, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffB)); + + mergeLeftToRight(diffC); + assertEquals(MERGED, diffA.getState()); + assertEquals(MERGED, diffB.getState()); + assertEquals(MERGED, diffC.getState()); + } + + /** + * Tests: A => B, C <br/> + * Merge: A <br/> + * Resulting Merges: A, B, C <br/> + * A implies B, and C so we merge A and set B and C to MERGED automatically. + */ + @Test + public void testsAImpliesBCMergeA() { + Diff diffA = createDiff("DiffA"); //$NON-NLS-1$ + Diff diffB = createDiff("DiffB"); //$NON-NLS-1$ + Diff diffC = createDiff("DiffC"); //$NON-NLS-1$ + diffA.getImplies().add(diffB); + diffA.getImplies().add(diffC); + + Set<Diff> resultingMerges = getDirectResultingMerges(diffA); + assertEquals(2, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffB)); + assertTrue(resultingMerges.contains(diffC)); + + resultingMerges = getDirectResultingMerges(diffB); + assertEquals(1, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffA)); + + resultingMerges = getDirectResultingMerges(diffC); + assertEquals(1, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffA)); + + mergeLeftToRight(diffA); + assertEquals(MERGED, diffA.getState()); + assertEquals(MERGED, diffB.getState()); + assertEquals(MERGED, diffC.getState()); + } + + /** + * Tests: A => B, C <br/> + * Merge: B <br/> + * Resulting Merges: A, B, C <br/> + * In EMF Compare, implication means that we always merge A instead of B (B and C require no merging). + * Therefore we merge A and set B and C to MERGED automatically. + */ + @Test + public void testsAImpliesBCMergeB() { + Diff diffA = createDiff("DiffA"); //$NON-NLS-1$ + Diff diffB = createDiff("DiffB"); //$NON-NLS-1$ + Diff diffC = createDiff("DiffC"); //$NON-NLS-1$ + diffA.getImplies().add(diffB); + diffA.getImplies().add(diffC); + + Set<Diff> resultingMerges = getDirectResultingMerges(diffA); + assertEquals(2, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffB)); + assertTrue(resultingMerges.contains(diffC)); + + resultingMerges = getDirectResultingMerges(diffB); + assertEquals(1, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffA)); + + resultingMerges = getDirectResultingMerges(diffC); + assertEquals(1, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffA)); + + mergeLeftToRight(diffB); + assertEquals(MERGED, diffA.getState()); + assertEquals(MERGED, diffB.getState()); + assertEquals(MERGED, diffC.getState()); + } + + /** + * Tests: A => B, C <br/> + * Merge: B <br/> + * Resulting Merges: A, B, C <br/> + * In EMF Compare, implication means that we always merge A instead of C (B and C require no merging). + * Therefore we merge A and set B and C to MERGED automatically. + */ + @Test + public void testsAImpliesBCMergeC() { + Diff diffA = createDiff("DiffA"); //$NON-NLS-1$ + Diff diffB = createDiff("DiffB"); //$NON-NLS-1$ + Diff diffC = createDiff("DiffC"); //$NON-NLS-1$ + diffA.getImplies().add(diffB); + diffA.getImplies().add(diffC); + + Set<Diff> resultingMerges = getDirectResultingMerges(diffA); + assertEquals(2, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffB)); + assertTrue(resultingMerges.contains(diffC)); + + resultingMerges = getDirectResultingMerges(diffB); + assertEquals(1, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffA)); + + resultingMerges = getDirectResultingMerges(diffC); + assertEquals(1, resultingMerges.size()); + assertTrue(resultingMerges.contains(diffA)); + + mergeLeftToRight(diffC); + assertEquals(MERGED, diffA.getState()); + assertEquals(MERGED, diffB.getState()); + assertEquals(MERGED, diffC.getState()); + } + + protected Diff createDiff(final String name) { + return new DiffSpec() { + @Override + public String toString() { + return name; + } + }; + } +} diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/MultipleMergeTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/MultipleMergeTest.java index 2d92d7186..fe9e57c90 100644 --- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/MultipleMergeTest.java +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/MultipleMergeTest.java @@ -32,6 +32,7 @@ import com.google.common.collect.Iterators; import com.google.common.collect.Lists; import java.io.IOException; +import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -46,6 +47,7 @@ import org.eclipse.emf.compare.FeatureMapChange; import org.eclipse.emf.compare.Match; import org.eclipse.emf.compare.ReferenceChange; import org.eclipse.emf.compare.internal.utils.ComparisonUtil; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.scope.DefaultComparisonScope; import org.eclipse.emf.compare.scope.IComparisonScope; @@ -68,7 +70,7 @@ public class MultipleMergeTest { private TwoWayMergeInputData twoWayInput = new TwoWayMergeInputData(); - private IMerger.Registry mergerRegistry = IMerger.RegistryImpl.createStandaloneInstance(); + private BatchMerger batchMerger = new BatchMerger(IMerger.RegistryImpl.createStandaloneInstance()); /** * @see ComplexMergeTest for a parametric test of all combinations of merge order. This test is here to @@ -122,16 +124,14 @@ public class MultipleMergeTest { // left: 8923410, right: 62930147 final ReferenceChange rightAdOfNode9 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT), added("Root.Node9"))); - mergerRegistry.getHighestRankingMerger(rightAdOfNode9).copyLeftToRight(rightAdOfNode9, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(rightAdOfNode9), new BasicMonitor()); // left: 8923410, right: 6230147 final ReferenceChange rightMoveOfNode1 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT), moved("Root.Node1", "containmentRef1"))); // revert move of Node 1 in right. It should be re-positioned right before 2 - mergerRegistry.getHighestRankingMerger(rightMoveOfNode1).copyLeftToRight(rightMoveOfNode1, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(rightMoveOfNode1), new BasicMonitor()); assertValueIndexIs(rightMoveOfNode1, false, 1); // left: 8923410, right: 6123047 @@ -139,16 +139,14 @@ public class MultipleMergeTest { final ReferenceChange rightAddOfNode0 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT), added("Root.Node0"))); // revert addition of 0 in right - mergerRegistry.getHighestRankingMerger(rightAddOfNode0).copyLeftToRight(rightAddOfNode0, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(rightAddOfNode0), new BasicMonitor()); // left: 8923410, right: 612347 final ReferenceChange rightMoveOfNode6 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT), moved("Root.Node6", "containmentRef1"))); // Revert move of 6 in right. - mergerRegistry.getHighestRankingMerger(rightMoveOfNode6).copyLeftToRight(rightMoveOfNode6, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(rightMoveOfNode6), new BasicMonitor()); assertValueIndexIs(rightMoveOfNode6, false, 4); // left: 8923410, right: 123467 @@ -156,8 +154,7 @@ public class MultipleMergeTest { final ReferenceChange rightDeleteOfNode5 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT), removed("Root.Node5"))); // delete of Node 5 (pseudo-conflict) => no change - mergerRegistry.getHighestRankingMerger(rightDeleteOfNode5).copyLeftToRight(rightDeleteOfNode5, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(rightDeleteOfNode5), new BasicMonitor()); assertValueIndexIs(rightDeleteOfNode5, false, -1); // left: 8923410, right: 123467 @@ -168,8 +165,7 @@ public class MultipleMergeTest { final ReferenceChange leftAddOfNode8 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), added("Root.Node8"))); // LCS is currently {2, 3, 4}. Insertion index is right before 2. - mergerRegistry.getHighestRankingMerger(leftAddOfNode8).copyLeftToRight(leftAddOfNode8, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(leftAddOfNode8), new BasicMonitor()); assertValueIndexIs(leftAddOfNode8, false, 1); // left: 8923410, right: 1823467 @@ -178,8 +174,7 @@ public class MultipleMergeTest { final ReferenceChange leftAddOfNode9 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), added("Root.Node9"))); // LCS is now {8, 2, 3, 4}. Insertion should be right after 8 - mergerRegistry.getHighestRankingMerger(leftAddOfNode9).copyLeftToRight(leftAddOfNode9, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(leftAddOfNode9), new BasicMonitor()); assertValueIndexIs(leftAddOfNode9, false, 2); // left: 8923410, right: 18923467 @@ -188,8 +183,7 @@ public class MultipleMergeTest { final ReferenceChange leftMoveOfNode1 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), moved("Root.Node1", "containmentRef1"))); // LCS is {8, 9, 2, 3, 4}. 1 should be moved right after 4. - mergerRegistry.getHighestRankingMerger(leftMoveOfNode1).copyLeftToRight(leftMoveOfNode1, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(leftMoveOfNode1), new BasicMonitor()); assertValueIndexIs(leftMoveOfNode1, false, 5); // left: 8923410, right: 89234167 @@ -198,8 +192,7 @@ public class MultipleMergeTest { final ReferenceChange leftAddOfNode0 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), added("Root.Node0"))); // LCS is now {8, 9, 2, 3, 4, 1}. 0 should be added right after 1 - mergerRegistry.getHighestRankingMerger(leftAddOfNode0).copyLeftToRight(leftAddOfNode0, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(leftAddOfNode0), new BasicMonitor()); assertValueIndexIs(leftAddOfNode0, false, 6); // left: 8923410, right: 892341067 @@ -208,8 +201,7 @@ public class MultipleMergeTest { // These diff won't even be presented to the user, but let's merge it anyway. final ReferenceChange leftDeleteOfNode5 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), removed("Root.Node5"))); - mergerRegistry.getHighestRankingMerger(leftDeleteOfNode5).copyLeftToRight(leftDeleteOfNode5, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(leftDeleteOfNode5), new BasicMonitor()); assertValueIndexIs(leftDeleteOfNode5, false, -1); // left: 8923410, right: 892341067 @@ -217,8 +209,7 @@ public class MultipleMergeTest { // remove Node6 final ReferenceChange leftDeleteOfNode6 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), removed("Root.Node6"))); - mergerRegistry.getHighestRankingMerger(leftDeleteOfNode6).copyLeftToRight(leftDeleteOfNode6, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(leftDeleteOfNode6), new BasicMonitor()); assertValueIndexIs(leftDeleteOfNode6, false, -1); // left: 8923410, right: 89234107 @@ -226,7 +217,7 @@ public class MultipleMergeTest { // merge 7 (remove Node7) final ReferenceChange diff7 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), removed("Root.Node7"))); - mergerRegistry.getHighestRankingMerger(diff7).copyLeftToRight(diff7, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff7), new BasicMonitor()); assertValueIndexIs(diff7, false, -1); // left: 8923410, right: 8923410 @@ -263,8 +254,7 @@ public class MultipleMergeTest { // Revert delete of 6 on the left side final ReferenceChange leftDeleteOfNode6 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), removed("Root.Node6"))); - mergerRegistry.getHighestRankingMerger(leftDeleteOfNode6).copyRightToLeft(leftDeleteOfNode6, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(leftDeleteOfNode6), new BasicMonitor()); assertValueIndexIs(leftDeleteOfNode6, true, 5); // left: 89234610, right: 62930147 @@ -272,8 +262,7 @@ public class MultipleMergeTest { // Revert add of 9 on the left side final ReferenceChange leftAddOfNode9 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), added("Root.Node9"))); - mergerRegistry.getHighestRankingMerger(leftAddOfNode9).copyRightToLeft(leftAddOfNode9, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(leftAddOfNode9), new BasicMonitor()); assertValueIndexIs(leftAddOfNode9, true, -1); // left: 8234610, right: 62930147 @@ -281,8 +270,7 @@ public class MultipleMergeTest { // Revert delete of node 5, pseudo conflict -> does nothing final ReferenceChange leftDeleteOfNode5 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), removed("Root.Node5"))); - mergerRegistry.getHighestRankingMerger(leftDeleteOfNode5).copyRightToLeft(leftDeleteOfNode5, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(leftDeleteOfNode5), new BasicMonitor()); assertValueIndexIs(leftDeleteOfNode5, true, -1); // left: 8234610, right: 62930147 @@ -290,8 +278,7 @@ public class MultipleMergeTest { // Revert add of 0 on the left side final ReferenceChange leftAddOfNode0 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), added("Root.Node0"))); - mergerRegistry.getHighestRankingMerger(leftAddOfNode0).copyRightToLeft(leftAddOfNode0, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(leftAddOfNode0), new BasicMonitor()); assertValueIndexIs(leftAddOfNode0, true, -1); // left: 823461, right: 62930147 @@ -299,8 +286,7 @@ public class MultipleMergeTest { // Revert move of 1 in left final ReferenceChange leftMoveOfNode1 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), moved("Root.Node1", "containmentRef1"))); - mergerRegistry.getHighestRankingMerger(leftMoveOfNode1).copyRightToLeft(leftMoveOfNode1, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(leftMoveOfNode1), new BasicMonitor()); assertValueIndexIs(leftMoveOfNode1, true, 1); // left: 812346, right: 62930147 @@ -310,8 +296,7 @@ public class MultipleMergeTest { // move 6 final ReferenceChange rightMoveOfNode6 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT), moved("Root.Node6", "containmentRef1"))); - mergerRegistry.getHighestRankingMerger(rightMoveOfNode6).copyRightToLeft(rightMoveOfNode6, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(rightMoveOfNode6), new BasicMonitor()); assertValueIndexIs(rightMoveOfNode6, true, 2); // left: 816234, right: 62930147 @@ -319,8 +304,7 @@ public class MultipleMergeTest { // add 9 final ReferenceChange rightAddOfNode9 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT), added("Root.Node9"))); - mergerRegistry.getHighestRankingMerger(rightAddOfNode9).copyRightToLeft(rightAddOfNode9, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(rightAddOfNode9), new BasicMonitor()); assertValueIndexIs(rightAddOfNode9, true, 4); // left: 8162934, right: 62930147 @@ -328,8 +312,7 @@ public class MultipleMergeTest { // add 0 final ReferenceChange rightAddOfNode0 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT), added("Root.Node0"))); - mergerRegistry.getHighestRankingMerger(rightAddOfNode0).copyRightToLeft(rightAddOfNode0, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(rightAddOfNode0), new BasicMonitor()); assertValueIndexIs(rightAddOfNode0, true, 6); // left: 81629304, right: 62930147 @@ -337,8 +320,7 @@ public class MultipleMergeTest { // move 1 final ReferenceChange rightMoveOfNode1 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT), moved("Root.Node1", "containmentRef1"))); - mergerRegistry.getHighestRankingMerger(rightMoveOfNode1).copyRightToLeft(rightMoveOfNode1, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(rightMoveOfNode1), new BasicMonitor()); assertValueIndexIs(rightMoveOfNode1, true, 6); // left: 86293014, right: 62930147 @@ -346,8 +328,7 @@ public class MultipleMergeTest { // remove 5 (again, pseudo-conflict) -> no effect final ReferenceChange rightDeleteOfNode5 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.RIGHT), removed("Root.Node5"))); - mergerRegistry.getHighestRankingMerger(rightDeleteOfNode5).copyRightToLeft(rightDeleteOfNode5, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(rightDeleteOfNode5), new BasicMonitor()); assertValueIndexIs(rightDeleteOfNode5, true, -1); // left: 86293014, right: 62930147 @@ -355,8 +336,7 @@ public class MultipleMergeTest { // revert add 8 final ReferenceChange leftAddOfNode8 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), added("Root.Node8"))); - mergerRegistry.getHighestRankingMerger(leftAddOfNode8).copyRightToLeft(leftAddOfNode8, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(leftAddOfNode8), new BasicMonitor()); assertValueIndexIs(leftAddOfNode8, false, -1); // left: 6293014, right: 62930147 @@ -364,8 +344,7 @@ public class MultipleMergeTest { // revert delete 7 final ReferenceChange leftDeleteOfNode7 = (ReferenceChange)Iterators.find(differences.iterator(), and(fromSide(DifferenceSource.LEFT), removed("Root.Node7"))); - mergerRegistry.getHighestRankingMerger(leftDeleteOfNode7).copyRightToLeft(leftDeleteOfNode7, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(leftDeleteOfNode7), new BasicMonitor()); assertValueIndexIs(leftDeleteOfNode7, false, 7); // left: 62930147, right: 62930147 @@ -408,19 +387,19 @@ public class MultipleMergeTest { final ReferenceChange diff6 = (ReferenceChange)Iterators.find(differences.iterator(), addedToReference("Requirements.F", "source", "Requirements.E")); - mergerRegistry.getHighestRankingMerger(diff1).copyLeftToRight(diff1, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff1), new BasicMonitor()); // Check that diff1 got properly merged assertMerged(comparison, diff1, false, false); // And validate that diff2 got merged as an equivalent diff assertMerged(comparison, diff2, false, false); - mergerRegistry.getHighestRankingMerger(diff3).copyLeftToRight(diff3, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff3), new BasicMonitor()); // Check that diff3 got properly merged assertMerged(comparison, diff3, false, false); // And validate that diff4 got merged as an equivalent diff assertMerged(comparison, diff4, false, false); - mergerRegistry.getHighestRankingMerger(diff5).copyLeftToRight(diff5, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff5), new BasicMonitor()); // Check that diff5 got properly merged assertMerged(comparison, diff5, false, false); // And validate that diff6 got merged as an equivalent diff @@ -460,17 +439,17 @@ public class MultipleMergeTest { final ReferenceChange diff6 = (ReferenceChange)Iterators.find(differences.iterator(), addedToReference("Requirements.F", "source", "Requirements.E")); - mergerRegistry.getHighestRankingMerger(diff1).copyRightToLeft(diff1, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff1), new BasicMonitor()); // Check that diff1 got properly merged (we're unsetting values) assertMerged(comparison, diff1, true, true); // And validate that diff2 got merged as an equivalent diff assertMerged(comparison, diff2, true, true); - mergerRegistry.getHighestRankingMerger(diff3).copyRightToLeft(diff3, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff3), new BasicMonitor()); assertMerged(comparison, diff3, true, true); assertMerged(comparison, diff4, true, true); - mergerRegistry.getHighestRankingMerger(diff5).copyRightToLeft(diff5, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff5), new BasicMonitor()); assertMerged(comparison, diff5, true, true); assertMerged(comparison, diff6, true, true); @@ -503,11 +482,11 @@ public class MultipleMergeTest { final ReferenceChange diff4 = (ReferenceChange)Iterators.find(differences.iterator(), addedToReference("Requirements.A", "source", "Requirements.B")); - mergerRegistry.getHighestRankingMerger(diff1).copyLeftToRight(diff1, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff1), new BasicMonitor()); assertMerged(comparison, diff1, false, false); assertMerged(comparison, diff2, false, false); - mergerRegistry.getHighestRankingMerger(diff3).copyLeftToRight(diff3, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff3), new BasicMonitor()); assertMerged(comparison, diff3, false, false); assertMerged(comparison, diff4, false, false); @@ -540,11 +519,11 @@ public class MultipleMergeTest { final ReferenceChange diff4 = (ReferenceChange)Iterators.find(differences.iterator(), addedToReference("Requirements.A", "source", "Requirements.B")); - mergerRegistry.getHighestRankingMerger(diff1).copyRightToLeft(diff1, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff1), new BasicMonitor()); assertMerged(comparison, diff1, true, true); assertMerged(comparison, diff2, true, true); - mergerRegistry.getHighestRankingMerger(diff3).copyRightToLeft(diff3, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff3), new BasicMonitor()); assertMerged(comparison, diff3, true, true); assertMerged(comparison, diff4, true, true); @@ -599,19 +578,19 @@ public class MultipleMergeTest { final ReferenceChange diff12 = (ReferenceChange)Iterators.find(differences.iterator(), addedToReference("Requirements", "containmentRef1", "Requirements.F")); - mergerRegistry.getHighestRankingMerger(diff1).copyLeftToRight(diff1, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff1), new BasicMonitor()); assertMerged(comparison, diff1, false, false); assertMerged(comparison, diff2, false, false); assertSame(DifferenceState.MERGED, diff7.getState()); assertSame(DifferenceState.MERGED, diff8.getState()); - mergerRegistry.getHighestRankingMerger(diff3).copyLeftToRight(diff3, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff3), new BasicMonitor()); assertMerged(comparison, diff3, false, false); assertMerged(comparison, diff4, false, false); assertSame(DifferenceState.MERGED, diff9.getState()); assertSame(DifferenceState.MERGED, diff10.getState()); - mergerRegistry.getHighestRankingMerger(diff5).copyLeftToRight(diff5, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff5), new BasicMonitor()); assertMerged(comparison, diff5, false, false); assertMerged(comparison, diff6, false, false); assertSame(DifferenceState.MERGED, diff11.getState()); @@ -670,31 +649,31 @@ public class MultipleMergeTest { // Removing the link between A and B does not necessarily means removing A and B // The "required" diffs will ne be merged - mergerRegistry.getHighestRankingMerger(diff1).copyRightToLeft(diff1, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff1), new BasicMonitor()); assertMerged(comparison, diff1, true, true); assertMerged(comparison, diff2, true, true); assertSame(DifferenceState.UNRESOLVED, diff7.getState()); assertSame(DifferenceState.UNRESOLVED, diff8.getState()); - mergerRegistry.getHighestRankingMerger(diff3).copyRightToLeft(diff3, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff3), new BasicMonitor()); assertMerged(comparison, diff3, true, true); assertMerged(comparison, diff4, true, true); assertSame(DifferenceState.UNRESOLVED, diff9.getState()); assertSame(DifferenceState.UNRESOLVED, diff10.getState()); - mergerRegistry.getHighestRankingMerger(diff5).copyRightToLeft(diff5, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff5), new BasicMonitor()); assertMerged(comparison, diff5, true, true); assertMerged(comparison, diff6, true, true); assertSame(DifferenceState.UNRESOLVED, diff11.getState()); assertSame(DifferenceState.UNRESOLVED, diff12.getState()); // Merge the 6 remaining diffs - mergerRegistry.getHighestRankingMerger(diff7).copyRightToLeft(diff7, new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(diff8).copyRightToLeft(diff8, new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(diff9).copyRightToLeft(diff9, new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(diff10).copyRightToLeft(diff10, new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(diff11).copyRightToLeft(diff11, new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(diff12).copyRightToLeft(diff12, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff7), new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff8), new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff9), new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff10), new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff11), new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff12), new BasicMonitor()); comparison = EMFCompare.builder().build().compare(scope); assertEquals(0, comparison.getDifferences().size()); @@ -728,7 +707,7 @@ public class MultipleMergeTest { final ReferenceChange diff4 = (ReferenceChange)Iterators.find(differences.iterator(), changedReference("Requirements.C", "source", null, "Requirements.A")); - mergerRegistry.getHighestRankingMerger(diff2).copyLeftToRight(diff2, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff2), new BasicMonitor()); assertSame(DifferenceState.MERGED, diff1.getState()); assertMerged(comparison, diff2, false, false); assertMerged(comparison, diff3, true, false); @@ -766,13 +745,13 @@ public class MultipleMergeTest { final ReferenceChange diff4 = (ReferenceChange)Iterators.find(differences.iterator(), changedReference("Requirements.C", "source", null, "Requirements.A")); - mergerRegistry.getHighestRankingMerger(diff1).copyLeftToRight(diff1, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff1), new BasicMonitor()); assertSame(DifferenceState.MERGED, diff1.getState()); assertSame(DifferenceState.UNRESOLVED, diff2.getState()); assertSame(DifferenceState.UNRESOLVED, diff3.getState()); assertSame(DifferenceState.UNRESOLVED, diff4.getState()); - mergerRegistry.getHighestRankingMerger(diff2).copyLeftToRight(diff2, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff2), new BasicMonitor()); assertMerged(comparison, diff2, false, false); assertMerged(comparison, diff3, true, false); assertMerged(comparison, diff4, false, false); @@ -809,7 +788,7 @@ public class MultipleMergeTest { final ReferenceChange diff4 = (ReferenceChange)Iterators.find(differences.iterator(), changedReference("Requirements.C", "source", null, "Requirements.A")); - mergerRegistry.getHighestRankingMerger(diff2).copyRightToLeft(diff2, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff2), new BasicMonitor()); assertSame(DifferenceState.UNRESOLVED, diff1.getState()); assertMerged(comparison, diff3, false, true); assertMerged(comparison, diff4, true, true); @@ -823,7 +802,7 @@ public class MultipleMergeTest { assertEquals("B", nodeB.eGet(nodeB.eClass().getEStructuralFeature("name"))); assertSame(nodeB, nodeA.eGet(diff2.getReference())); - mergerRegistry.getHighestRankingMerger(diff1).copyRightToLeft(diff1, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff1), new BasicMonitor()); comparison = EMFCompare.builder().build().compare(scope); assertEquals(0, comparison.getDifferences().size()); @@ -861,14 +840,14 @@ public class MultipleMergeTest { final ReferenceChange diff5 = (ReferenceChange)Iterators.find(differences.iterator(), changedReference("Requirements.C", "source", null, "Requirements.A")); - mergerRegistry.getHighestRankingMerger(diff1).copyLeftToRight(diff1, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff1), new BasicMonitor()); assertMerged(comparison, diff1, false, false); assertSame(DifferenceState.UNRESOLVED, diff2.getState()); assertSame(DifferenceState.UNRESOLVED, diff3.getState()); assertSame(DifferenceState.UNRESOLVED, diff4.getState()); assertSame(DifferenceState.UNRESOLVED, diff5.getState()); - mergerRegistry.getHighestRankingMerger(diff2).copyLeftToRight(diff2, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff2), new BasicMonitor()); // B has been deleted : unset element in right assertMerged(comparison, diff2, true, false); // Change A.destination from "B" to "C" @@ -918,7 +897,7 @@ public class MultipleMergeTest { // 1 is required by 3, which is required by 2 and equivalent to 4 and 5. // Resetting 1 should thus reset all other diffs. - mergerRegistry.getHighestRankingMerger(diff1).copyRightToLeft(diff1, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff1), new BasicMonitor()); assertMerged(comparison, diff1, true, true); assertMerged(comparison, diff2, false, true); @@ -974,11 +953,11 @@ public class MultipleMergeTest { * diff1 and diff2 will also be set to status "merged" although the reference to be set is still * missing. */ - mergerRegistry.getHighestRankingMerger(diff3).copyLeftToRight(diff3, new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(diff1).copyLeftToRight(diff1, new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(diff2).copyLeftToRight(diff2, new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(diff4).copyLeftToRight(diff4, new BasicMonitor()); - mergerRegistry.getHighestRankingMerger(diff5).copyLeftToRight(diff5, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff3), new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff1), new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff2), new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff4), new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff5), new BasicMonitor()); // check if no differences between models are left comparison = EMFCompare.builder().build().compare(scope); @@ -1004,12 +983,12 @@ public class MultipleMergeTest { * equivalences, the equivalences will also be set to status "merged" although the reference to be set * is still missing. */ - mergerRegistry.getHighestRankingMerger(unsetDiff).copyRightToLeft(unsetDiff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(unsetDiff), new BasicMonitor()); // merge the remaining diffs for (Diff diff : differences) { if (diff != unsetDiff) { - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); } } @@ -1043,12 +1022,12 @@ public class MultipleMergeTest { * equivalences, the equivalences will also be set to status "merged" although the reference to be set * is still missing. */ - mergerRegistry.getHighestRankingMerger(unsetDiff).copyLeftToRight(unsetDiff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(unsetDiff), new BasicMonitor()); // merge the remaining differences for (Diff diff : differences) { if (diff != unsetDiff) { - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); } } @@ -1077,12 +1056,12 @@ public class MultipleMergeTest { * equivalences, the equivalences will also be set to status "merged" although the reference to be set * is still missing. */ - mergerRegistry.getHighestRankingMerger(unsetDiff).copyRightToLeft(unsetDiff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(unsetDiff), new BasicMonitor()); // merge the remaining differences for (Diff diff : differences) { if (diff != unsetDiff) { - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); } } @@ -1119,8 +1098,7 @@ public class MultipleMergeTest { // By merging diff1 (setCSourceDiff) the model will be in a state where the remaining diffs // describe actions which already occurred. - mergerRegistry.getHighestRankingMerger(setCSourceDiff).copyLeftToRight(setCSourceDiff, - new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(setCSourceDiff), new BasicMonitor()); // Check if the non-equivalent diff is also set to merged assertEquals(DifferenceState.MERGED, setDSourceDiff.getState()); @@ -1158,8 +1136,7 @@ public class MultipleMergeTest { // By merging diff1 (setCSourceDiff) R2L the model will be in a state where the remaining diffs // describe actions which already occurred. - mergerRegistry.getHighestRankingMerger(setCSourceDiff).copyRightToLeft(setCSourceDiff, - new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(setCSourceDiff), new BasicMonitor()); // Check if the non-equivalent diff is marked as merged assertEquals(DifferenceState.MERGED, setDSourceDiff.getState()); @@ -1188,12 +1165,12 @@ public class MultipleMergeTest { * its equivalences, the equivalences will also be set to status "merged" although the reference to be * added is still missing. */ - mergerRegistry.getHighestRankingMerger(deleteDiff).copyLeftToRight(deleteDiff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(deleteDiff), new BasicMonitor()); // merge the remaining differences for (Diff diff : differences) { if (diff != deleteDiff) { - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); } } @@ -1221,12 +1198,12 @@ public class MultipleMergeTest { * proper looking at its equivalences, the equivalences will also be set to status "merged" although * the reference to be added is still missing. */ - mergerRegistry.getHighestRankingMerger(deleteDiff).copyRightToLeft(deleteDiff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(deleteDiff), new BasicMonitor()); // merge the remaining differences for (Diff diff : differences) { if (diff != deleteDiff) { - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); } } @@ -1258,12 +1235,12 @@ public class MultipleMergeTest { assertNotNull(addFirstKey); // Execute FeatureMapChange to test if it properly resolves its dependencies - mergerRegistry.getHighestRankingMerger(addFirstKey).copyLeftToRight(addFirstKey, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(addFirstKey), new BasicMonitor()); // Execute the remaining differences for (Diff diff : differences) { if (diff != addFirstKey) { - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); } } @@ -1300,13 +1277,13 @@ public class MultipleMergeTest { // Execute FeatureMapChanges first to test if they properly resolve their dependencies for (Diff diff : featureMapChanges) { - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); } // Execute the remaining differences for (Diff diff : differences) { if (!featureMapChanges.contains(diff)) { - mergerRegistry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor()); + batchMerger.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); } } @@ -1331,9 +1308,9 @@ public class MultipleMergeTest { // Just test no NPE is raising for (Diff diff : differences) { ComparisonUtil.getSubDiffs(true).apply(diff); - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); ComparisonUtil.getSubDiffs(true).apply(diff); - mergerRegistry.getHighestRankingMerger(diff).copyLeftToRight(diff, new BasicMonitor()); + batchMerger.copyAllLeftToRight(Arrays.asList(diff), new BasicMonitor()); } } diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/RefineMergeTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/RefineMergeTest.java index 8a21ac2a2..bf91df850 100644 --- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/RefineMergeTest.java +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/merge/RefineMergeTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015 Obeo. + * Copyright (c) 2015, 2016 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 @@ -7,22 +7,25 @@ * * Contributors: * Obeo - initial API and implementation + * Martin Fleck - bug 507177 *******************************************************************************/ package org.eclipse.emf.compare.tests.merge; +import static org.eclipse.emf.compare.DifferenceState.MERGED; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.util.Set; import org.eclipse.emf.compare.Diff; -import org.eclipse.emf.compare.DifferenceState; import org.eclipse.emf.compare.internal.spec.DiffSpec; import org.eclipse.emf.compare.merge.AbstractMerger; import org.junit.Test; public class RefineMergeTest { + private static final boolean MERGE_RIGHT_TO_LEFT = true; + private final AbstractMerger merger = new AbstractMerger() { public boolean isMergerFor(Diff target) { return true; @@ -30,11 +33,12 @@ public class RefineMergeTest { }; /** - * If a diff refines another, we have to check if the "macro" diff has to be merged with it. + * If a diff refines another, we have to check if the "macro" diff has to be merged with it. Refinement + * diffs can only be merged together as a whole. Therefore, refined diffs should have the refining diffs + * as dependency and refining diffs the refined diff as resulting diff. */ @Test public void testRefineOnGetDirectResultingMerges() { - // Create diffs Diff diff1 = new DiffSpec(); Diff diff2 = new DiffSpec(); @@ -43,45 +47,48 @@ public class RefineMergeTest { diff3.getRefinedBy().add(diff1); diff3.getRefinedBy().add(diff2); - // First call : diff3 must not to be in the merge dependencies, cause diff2 is not merged. - Set<Diff> dependencies = merger.getDirectResultingMerges(diff1, true); - assertTrue(dependencies.isEmpty()); - // Merge diff2 - diff2.setState(DifferenceState.MERGED); - // Second call : diff3 must be in the merge dependencies, cause diff2 has been merged. - dependencies = merger.getDirectResultingMerges(diff1, true); - assertEquals(1, dependencies.size()); - assertTrue(dependencies.contains(diff3)); + // First call: diff3 must be merged, because refinements are only merged together as a whole. + Set<Diff> directMergeDependencies = merger.getDirectMergeDependencies(diff1, MERGE_RIGHT_TO_LEFT); + Set<Diff> resultingMerges = merger.getDirectResultingMerges(diff1, MERGE_RIGHT_TO_LEFT); + assertEquals(1, resultingMerges.size()); + assertTrue(resultingMerges.contains(diff3)); + assertTrue(directMergeDependencies.isEmpty()); - } + directMergeDependencies = merger.getDirectMergeDependencies(diff2, MERGE_RIGHT_TO_LEFT); + resultingMerges = merger.getDirectResultingMerges(diff2, MERGE_RIGHT_TO_LEFT); + assertTrue(directMergeDependencies.isEmpty()); + assertEquals(1, resultingMerges.size()); + assertTrue(resultingMerges.contains(diff3)); - @Test - public void testRefineOnGetDirectResultingMerges_2() { + directMergeDependencies = merger.getDirectMergeDependencies(diff3, MERGE_RIGHT_TO_LEFT); + resultingMerges = merger.getDirectResultingMerges(diff3, MERGE_RIGHT_TO_LEFT); + assertEquals(2, directMergeDependencies.size()); + assertTrue(directMergeDependencies.contains(diff1)); + assertTrue(directMergeDependencies.contains(diff2)); + assertTrue(resultingMerges.isEmpty()); - // Create diffs - Diff diff1 = new DiffSpec(); - Diff diff2 = new DiffSpec(); - Diff diff3 = new DiffSpec(); + // Merge diff2 + diff2.setState(MERGED); - Diff diff4 = new DiffSpec(); - diff4.getRefinedBy().add(diff1); - diff4.getRefinedBy().add(diff2); - diff4.getRefinedBy().add(diff3); + // Second call: there should not be any changes + directMergeDependencies = merger.getDirectMergeDependencies(diff1, MERGE_RIGHT_TO_LEFT); + resultingMerges = merger.getDirectResultingMerges(diff1, MERGE_RIGHT_TO_LEFT); + assertEquals(1, resultingMerges.size()); + assertTrue(resultingMerges.contains(diff3)); + assertTrue(directMergeDependencies.isEmpty()); - // First call : diff4 must not to be in the merge dependencies, cause diff2 & diff3 are not merged. - Set<Diff> dependencies = merger.getDirectResultingMerges(diff1, true); - assertTrue(dependencies.isEmpty()); - // Merge diff2 - diff2.setState(DifferenceState.MERGED); - // Second call : diff4 must not to be in the merge dependencies, cause diff3 is not merged. - dependencies = merger.getDirectResultingMerges(diff1, true); - assertTrue(dependencies.isEmpty()); - // Merge diff3 - diff3.setState(DifferenceState.MERGED); - // Third call : diff4 must be in the merge dependencies, cause diff2 & diff3 have been merged. - dependencies = merger.getDirectResultingMerges(diff1, true); - assertEquals(1, dependencies.size()); - assertTrue(dependencies.contains(diff4)); + directMergeDependencies = merger.getDirectMergeDependencies(diff2, MERGE_RIGHT_TO_LEFT); + resultingMerges = merger.getDirectResultingMerges(diff2, MERGE_RIGHT_TO_LEFT); + assertTrue(directMergeDependencies.isEmpty()); + assertEquals(1, resultingMerges.size()); + assertTrue(resultingMerges.contains(diff3)); + directMergeDependencies = merger.getDirectMergeDependencies(diff3, MERGE_RIGHT_TO_LEFT); + resultingMerges = merger.getDirectResultingMerges(diff3, MERGE_RIGHT_TO_LEFT); + assertEquals(2, directMergeDependencies.size()); + assertTrue(directMergeDependencies.contains(diff1)); + assertTrue(directMergeDependencies.contains(diff2)); + assertTrue(resultingMerges.isEmpty()); } + } 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 606545ac6..e61131af5 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 @@ -10,6 +10,7 @@ * Philip Langer - Adds additional test classes * Stefan Dirix - Adds additional test classes * Michael Borkowski - Adds additional test classes + * Martin Fleck - Add ImplicationMergeTest, GraphTest *******************************************************************************/ package org.eclipse.emf.compare.tests.suite; @@ -46,6 +47,7 @@ import org.eclipse.emf.compare.tests.merge.FeatureMaps2wayMergeTest; import org.eclipse.emf.compare.tests.merge.FeatureMaps3wayMergeTest; import org.eclipse.emf.compare.tests.merge.FeatureMapsConflictsMergeTest; import org.eclipse.emf.compare.tests.merge.FeatureMapsPseudoConflictsMergeTest; +import org.eclipse.emf.compare.tests.merge.ImplicationsMergeTest; import org.eclipse.emf.compare.tests.merge.IndividualMergeOutOfScopeValuesTest; import org.eclipse.emf.compare.tests.merge.IndividualMergeTest; import org.eclipse.emf.compare.tests.merge.MultiLineAttributeMergeTest; @@ -64,6 +66,7 @@ import org.eclipse.emf.compare.tests.scope.ComparisonScopeAdapterTest; import org.eclipse.emf.compare.tests.scope.DefaultComparisonScopeTest; import org.eclipse.emf.compare.tests.utils.EMFComparePredicatesTest; import org.eclipse.emf.compare.tests.utils.EqualityHelperTest; +import org.eclipse.emf.compare.tests.utils.GraphTest; import org.eclipse.emf.compare.tests.utils.MatchUtilFeatureContainsTest; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.resource.Resource; @@ -98,8 +101,8 @@ import junit.textui.TestRunner; MultiLineAttributeMergeTest.class, MonitorCancelTest.class, IdentifierEObjectMatcherTest.class, MatchUtilFeatureContainsTest.class, RefineMergeTest.class, Bug484557ConflictTest.class, Bug485266_MoveDeleteConflict_Test.class, ResourceAttachmentChangeBug492261.class, - ComparisonScopeAdapterTest.class, EMFComparePredicatesTest.class, - RankedAdapterFactoryRegistryTest.class, ComparisonUtilTest.class, }) + RankedAdapterFactoryRegistryTest.class, ComparisonScopeAdapterTest.class, + EMFComparePredicatesTest.class, ImplicationsMergeTest.class, GraphTest.class, }) public class AllTests { /** * Standalone launcher for all of compare's tests. diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/utils/AbstractGraphTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/utils/AbstractGraphTest.java new file mode 100644 index 000000000..79beec4eb --- /dev/null +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/utils/AbstractGraphTest.java @@ -0,0 +1,532 @@ +/******************************************************************************* + * Copyright (c) 2015, 2016 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 + * Alexandra Buzila - bug 478620 + * Martin Fleck - bug 507177 + *******************************************************************************/ +package org.eclipse.emf.compare.tests.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.emf.compare.graph.IGraph; +import org.eclipse.emf.compare.graph.PruningIterator; +import org.eclipse.emf.compare.internal.utils.Graph; +import org.junit.Test; + +/** + * We will use this to test the utility methods exposed by the {@link Graph}. + * + * @author <a href="mailto:axel.richard@obeo.fr">Axel Richard</a> + */ +@SuppressWarnings({"nls", "unchecked" }) +public abstract class AbstractGraphTest<E> { + protected abstract E toType(final String name); + + protected abstract IGraph<E> createGraph(); + + /** + * Test correct subgraph. + * + * <pre> + * _A_ + * / | \ + * B C D + * | | + * E F + * </pre> + */ + @Test + public void testBuildSubGraph() { + IGraph<E> graph = createGraph(); + graph.addChildren(toType("A"), ImmutableSet.of(toType("B"), toType("C"), toType("D"))); + graph.addChildren(toType("C"), ImmutableSet.of(toType("E"))); + graph.addChildren(toType("D"), ImmutableSet.of(toType("F"))); + + Set<E> subgraph = graph.getSubgraphContaining(toType("D"), ImmutableSet.of(toType("C"))); + assertEquals(4, subgraph.size()); + assertTrue( + subgraph.containsAll(Lists.newArrayList(toType("A"), toType("B"), toType("D"), toType("F")))); + } + + /** + * Test avoidance of infinite loops in cyclic graph. + * + * <pre> + * C-+ + * | | + * B-+ + * | + * A + * </pre> + */ + @Test + public void testPrune() { + IGraph<E> graph = createGraph(); + + graph.addChildren(toType("A"), ImmutableSet.of(toType("B"))); + graph.addChildren(toType("B"), ImmutableSet.of(toType("C"))); + graph.addChildren(toType("C"), ImmutableSet.of(toType("B"))); + PruningIterator<E> iterator = graph.breadthFirstIterator(); + while (iterator.hasNext()) { + iterator.next(); + iterator.prune(); + } + } + + /** + * Tests breadth first iteration with the following Graph: + * + * <pre> + * A I J + * / \ / / \ + * B C G K L + * / / \ / \ / \ + * D E F H M N + * + * We expect our iteration to go in the following order: + * three first items, in unspecified order : A, I, J + * next five, in unspecified order : B, C, G, K, L + * finally, still in unspecified order : D, E, F, H, M, N + * </pre> + */ + @Test + public void testBreadthFirstIteration() { + IGraph<E> graph = createGraph(); + + graph.addChildren(toType("A"), ImmutableSet.of(toType("B"), toType("C"))); + graph.addChildren(toType("B"), ImmutableSet.of(toType("D"))); + graph.addChildren(toType("C"), ImmutableSet.of(toType("E"), toType("F"))); + graph.addChildren(toType("I"), ImmutableSet.of(toType("G"))); + graph.addChildren(toType("G"), ImmutableSet.of(toType("F"), toType("H"))); + graph.addChildren(toType("J"), ImmutableSet.of(toType("K"), toType("L"))); + graph.addChildren(toType("L"), ImmutableSet.of(toType("M"), toType("N"))); + + Set<E> firstThree = Sets.newHashSet(toType("A"), toType("I"), toType("J")); + Set<E> nextFive = Sets.newHashSet(toType("B"), toType("C"), toType("G"), toType("K"), toType("L")); + Set<E> finalSix = Sets.newHashSet(toType("D"), toType("E"), toType("F"), toType("H"), toType("M"), + toType("N")); + + PruningIterator<E> iterator = graph.breadthFirstIterator(); + assertTrue(firstThree.remove(iterator.next())); + assertTrue(firstThree.remove(iterator.next())); + assertTrue(firstThree.remove(iterator.next())); + assertTrue(firstThree.isEmpty()); + + assertTrue(nextFive.remove(iterator.next())); + assertTrue(nextFive.remove(iterator.next())); + assertTrue(nextFive.remove(iterator.next())); + assertTrue(nextFive.remove(iterator.next())); + assertTrue(nextFive.remove(iterator.next())); + assertTrue(nextFive.isEmpty()); + + assertTrue(finalSix.remove(iterator.next())); + assertTrue(finalSix.remove(iterator.next())); + assertTrue(finalSix.remove(iterator.next())); + assertTrue(finalSix.remove(iterator.next())); + assertTrue(finalSix.remove(iterator.next())); + assertTrue(finalSix.remove(iterator.next())); + assertTrue(finalSix.isEmpty()); + assertFalse(iterator.hasNext()); + } + + /** + * This test case ensures that pruned elements are not returned in a scenario where the next iterator in + * the graph has already been prepared. This test uses the following graph: + * + * <pre> + * A B + * \ / + * C + * </pre> + */ + @Test + public void testBreadthFirstIteration_MultipleParents() { + IGraph<E> graph = createGraph(); + graph.addChildren(toType("A"), ImmutableSet.of(toType("C"))); + graph.addChildren(toType("B"), ImmutableSet.of(toType("C"))); + + PruningIterator<E> breadthFirstIterator = graph.breadthFirstIterator(); + + assertTrue(breadthFirstIterator.hasNext()); + assertEquals(toType("A"), breadthFirstIterator.next()); + + assertTrue(breadthFirstIterator.hasNext()); + assertEquals(toType("B"), breadthFirstIterator.next()); + + breadthFirstIterator.prune(); // prune all children of B: [C] + + assertFalse(breadthFirstIterator.hasNext()); + } + + /** + * This test case ensures that pruned elements are not returned in a scenario where the next iterator in + * the graph has already been prepared: + * + * <pre> + * _A_ B + * / | \ / + * D E C + * </pre> + */ + @Test + public void testBreadthFirstIteration_MultipleParentsMultipleChildren() { + IGraph<E> graph = createGraph(); + graph.addChildren(toType("A"), ImmutableSet.of(toType("C"), toType("D"), toType("E"))); + graph.addChildren(toType("B"), ImmutableSet.of(toType("C"), toType("D"))); + + PruningIterator<E> breadthFirstIterator = graph.breadthFirstIterator(); + + assertTrue(breadthFirstIterator.hasNext()); + assertEquals(toType("A"), breadthFirstIterator.next()); + + assertTrue(breadthFirstIterator.hasNext()); + assertEquals(toType("B"), breadthFirstIterator.next()); + + breadthFirstIterator.prune(); // prune all children of B: [C, D] + + assertTrue(breadthFirstIterator.hasNext()); + assertEquals(toType("E"), breadthFirstIterator.next()); + + assertFalse(breadthFirstIterator.hasNext()); + } + + /** + * This test case ensures that elements over multiple lvels are pruned correctly and are not returned + * through another path in the graph: + * + * <pre> + * A B + * / \ / + * D C + * \ / + * E + * </pre> + */ + @Test + public void testBreadthFirstIteration_PruneMultipleLevels() { + IGraph<E> graph = new Graph<E>(); + // first level + graph.addChildren(toType("A"), ImmutableSet.of(toType("D"), toType("C"))); + graph.addChildren(toType("B"), ImmutableSet.of(toType("C"))); + + // second level + graph.addChildren(toType("D"), ImmutableSet.of(toType("E"))); + graph.addChildren(toType("C"), ImmutableSet.of(toType("E"))); + + PruningIterator<E> breadthFirstIterator = graph.breadthFirstIterator(); + + // iterate over first level + assertTrue(breadthFirstIterator.hasNext()); + assertEquals(toType("A"), breadthFirstIterator.next()); + + assertTrue(breadthFirstIterator.hasNext()); + assertEquals(toType("B"), breadthFirstIterator.next()); + + // prune all children of B: [C and also E from the level below] + breadthFirstIterator.prune(); + + assertTrue(breadthFirstIterator.hasNext()); + assertEquals(toType("D"), breadthFirstIterator.next()); + + // no more children as C and E have been pruned + assertFalse(breadthFirstIterator.hasNext()); + } + + @Test + public void testTreeIteration_1() { + IGraph<E> graph = getAcyclicGraph(); + + Iterator<E> iteratorOnA = graph.depthFirstIterator(toType("A")); + assertEquals(toType("A"), iteratorOnA.next()); + assertEquals(toType("B"), iteratorOnA.next()); + assertEquals(toType("D"), iteratorOnA.next()); + assertEquals(toType("C"), iteratorOnA.next()); + assertEquals(toType("E"), iteratorOnA.next()); + assertEquals(toType("F"), iteratorOnA.next()); + assertFalse(iteratorOnA.hasNext()); + } + + @Test + public void testTreeIteration_2() { + IGraph<E> graph = getAcyclicGraph(); + + Iterator<E> iteratorOnC = graph.depthFirstIterator(toType("C")); + assertEquals(toType("C"), iteratorOnC.next()); + assertEquals(toType("E"), iteratorOnC.next()); + assertEquals(toType("F"), iteratorOnC.next()); + assertFalse(iteratorOnC.hasNext()); + } + + @Test + public void testTreeIteration_3() { + IGraph<E> graph = getAcyclicGraph(); + + Iterator<E> iteratorOnI = graph.depthFirstIterator(toType("I")); + assertEquals(toType("I"), iteratorOnI.next()); + assertEquals(toType("G"), iteratorOnI.next()); + assertEquals(toType("F"), iteratorOnI.next()); + assertEquals(toType("H"), iteratorOnI.next()); + assertFalse(iteratorOnI.hasNext()); + } + + @Test + public void testTreeIteration_4() { + IGraph<E> graph = getAcyclicGraph(); + + Iterator<E> iteratorOnJ = graph.depthFirstIterator(toType("J")); + assertEquals(toType("J"), iteratorOnJ.next()); + assertEquals(toType("K"), iteratorOnJ.next()); + assertEquals(toType("L"), iteratorOnJ.next()); + assertEquals(toType("M"), iteratorOnJ.next()); + assertEquals(toType("N"), iteratorOnJ.next()); + assertFalse(iteratorOnJ.hasNext()); + } + + @Test + public void testDepthIterationWithCycles_1() { + IGraph<E> graph = getGraphWithCycles(); + + Iterator<E> iteratorOnA = graph.depthFirstIterator(toType("A")); + assertEquals(toType("A"), iteratorOnA.next()); + assertEquals(toType("B"), iteratorOnA.next()); + assertEquals(toType("D"), iteratorOnA.next()); + assertEquals(toType("E"), iteratorOnA.next()); + assertEquals(toType("C"), iteratorOnA.next()); + assertEquals(toType("F"), iteratorOnA.next()); + assertEquals(toType("H"), iteratorOnA.next()); + + assertFalse(iteratorOnA.hasNext()); + } + + @Test + public void testDepthIterationWithCycles_2() { + IGraph<E> graph = getGraphWithCycles(); + + Iterator<E> iteratorOnC = graph.depthFirstIterator(toType("C")); + assertEquals(toType("C"), iteratorOnC.next()); + assertEquals(toType("A"), iteratorOnC.next()); + assertEquals(toType("B"), iteratorOnC.next()); + assertEquals(toType("D"), iteratorOnC.next()); + assertEquals(toType("E"), iteratorOnC.next()); + assertEquals(toType("F"), iteratorOnC.next()); + assertEquals(toType("H"), iteratorOnC.next()); + + assertFalse(iteratorOnC.hasNext()); + } + + @Test + public void testDepthIterationWithCycles_3() { + IGraph<E> graph = getGraphWithCycles(); + + Iterator<E> iteratorOnI = graph.depthFirstIterator(toType("I")); + assertEquals(toType("I"), iteratorOnI.next()); + assertEquals(toType("G"), iteratorOnI.next()); + assertEquals(toType("F"), iteratorOnI.next()); + assertEquals(toType("H"), iteratorOnI.next()); + + assertFalse(iteratorOnI.hasNext()); + } + + @Test + public void testDepthIterationWithCycles_4() { + IGraph<E> graph = getGraphWithCycles(); + + Iterator<E> iteratorOnJ = graph.depthFirstIterator(toType("J")); + assertEquals(toType("J"), iteratorOnJ.next()); + assertEquals(toType("K"), iteratorOnJ.next()); + assertEquals(toType("M"), iteratorOnJ.next()); + assertEquals(toType("L"), iteratorOnJ.next()); + assertEquals(toType("N"), iteratorOnJ.next()); + + assertFalse(iteratorOnJ.hasNext()); + } + + /** + * Test the BreadthFirstIterator with the following cyclic graph: + * + * <pre> + * A + * / \ + * B = C + * </pre> + */ + @Test + public void testBug503035_1() { + IGraph<E> graph = createGraph(); + + graph.addChildren(toType("A"), ImmutableSet.of(toType("B"), toType("C"))); + graph.addChildren(toType("B"), ImmutableSet.of(toType("C"))); + graph.addChildren(toType("C"), ImmutableSet.of(toType("B"))); + + Iterator<E> it = graph.breadthFirstIterator(); + assertTrue(it.hasNext()); + assertEquals(toType("A"), it.next()); + assertTrue(it.hasNext()); + assertEquals(toType("B"), it.next()); + assertTrue(it.hasNext()); + assertEquals(toType("C"), it.next()); + assertFalse(it.hasNext()); + } + + /** + * Test the BreadthFirstIterator with the following cyclic graph: + * + * <pre> + * A + * / \ + * B = C + * / + * D + * </pre> + */ + @Test + public void testBug503035_2() { + IGraph<E> graph = createGraph(); + + graph.addChildren(toType("A"), ImmutableSet.of(toType("B"), toType("C"))); + graph.addChildren(toType("B"), ImmutableSet.of(toType("D"), toType("C"))); + graph.addChildren(toType("C"), ImmutableSet.of(toType("B"))); + + Iterator<E> it = graph.breadthFirstIterator(); + assertTrue(it.hasNext()); + assertEquals(toType("A"), it.next()); + assertTrue(it.hasNext()); + assertEquals(toType("B"), it.next()); + assertTrue(it.hasNext()); + assertEquals(toType("C"), it.next()); + assertTrue(it.hasNext()); + assertEquals(toType("D"), it.next()); + assertFalse(it.hasNext()); + } + + /** + * Test the BreadthFirstIterator with the following cyclic graph: + * + * <pre> + * A B + * | | + * C = D + * </pre> + */ + @Test + public void testBug503035_3() { + IGraph<E> graph = createGraph(); + + graph.addChildren(toType("A"), ImmutableSet.of(toType("C"))); + graph.addChildren(toType("B"), ImmutableSet.of(toType("D"))); + graph.addChildren(toType("C"), ImmutableSet.of(toType("D"))); + graph.addChildren(toType("D"), ImmutableSet.of(toType("C"))); + + Iterator<E> it = graph.breadthFirstIterator(); + assertTrue(it.hasNext()); + assertEquals(toType("A"), it.next()); + assertTrue(it.hasNext()); + assertEquals(toType("B"), it.next()); + assertTrue(it.hasNext()); + assertEquals(toType("C"), it.next()); + assertTrue(it.hasNext()); + assertEquals(toType("D"), it.next()); + assertFalse(it.hasNext()); + } + + /** + * Test the BreadthFirstIterator with the following cyclic graph: + * + * <pre> + * A + * /|\ + * / | \ + * B C D + * \\===// + * </pre> + */ + @Test + public void testBug503035_4() { + IGraph<E> graph = createGraph(); + + graph.addChildren(toType("A"), ImmutableSet.of(toType("B"), toType("C"), toType("D"))); + graph.addChildren(toType("B"), ImmutableSet.of(toType("D"))); + graph.addChildren(toType("D"), ImmutableSet.of(toType("B"))); + + Iterator<E> it = graph.breadthFirstIterator(); + assertTrue(it.hasNext()); + assertEquals(toType("A"), it.next()); + assertTrue(it.hasNext()); + assertEquals(toType("B"), it.next()); + assertTrue(it.hasNext()); + assertEquals(toType("C"), it.next()); + assertTrue(it.hasNext()); + assertEquals(toType("D"), it.next()); + assertFalse(it.hasNext()); + } + + /** + * @return The following acyclic graph: + * + * <pre> + * A I J + * / \ / / \ + * B C G K L + * / / \ / \ / \ + * D E F H M N + * </pre> + */ + protected IGraph<E> getAcyclicGraph() { + IGraph<E> graph = createGraph(); + + graph.addChildren(toType("A"), ImmutableSet.of(toType("B"), toType("C"))); + graph.addChildren(toType("B"), ImmutableSet.of(toType("D"))); + graph.addChildren(toType("C"), ImmutableSet.of(toType("E"), toType("F"))); + graph.addChildren(toType("I"), ImmutableSet.of(toType("G"))); + graph.addChildren(toType("G"), ImmutableSet.of(toType("F"), toType("H"))); + graph.addChildren(toType("J"), ImmutableSet.of(toType("K"), toType("L"))); + graph.addChildren(toType("L"), ImmutableSet.of(toType("M"), toType("N"))); + + return graph; + } + + /** + * @return The following cyclic graph: + * + * <pre> + * A I J + * / \\ / / \ + * B C G K L + * / / \ / \ \ // \ + * D - E F = H M N + * </pre> + */ + protected IGraph<E> getGraphWithCycles() { + IGraph<E> graph = createGraph(); + + graph.addChildren(toType("A"), ImmutableSet.of(toType("B"), toType("C"))); + graph.addChildren(toType("B"), ImmutableSet.of(toType("D"))); + graph.addChildren(toType("D"), ImmutableSet.of(toType("E"))); + graph.addChildren(toType("C"), ImmutableSet.of(toType("A"), toType("E"), toType("F"))); + graph.addChildren(toType("I"), ImmutableSet.of(toType("G"))); + graph.addChildren(toType("G"), ImmutableSet.of(toType("F"), toType("H"))); + graph.addChildren(toType("J"), ImmutableSet.of(toType("K"), toType("L"))); + graph.addChildren(toType("K"), ImmutableSet.of(toType("M"))); + graph.addChildren(toType("M"), ImmutableSet.of(toType("L"))); + graph.addChildren(toType("L"), ImmutableSet.of(toType("M"), toType("N"))); + graph.addChildren(toType("F"), ImmutableSet.of(toType("H"))); + graph.addChildren(toType("H"), ImmutableSet.of(toType("F"))); + + return graph; + } +} diff --git a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/utils/GraphTest.java b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/utils/GraphTest.java index 02e10f59f..6379ae77b 100644 --- a/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/utils/GraphTest.java +++ b/plugins/org.eclipse.emf.compare.tests/src/org/eclipse/emf/compare/tests/utils/GraphTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015 Obeo and others. + * Copyright (c) 2015, 2016 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 @@ -8,419 +8,29 @@ * Contributors: * Obeo - initial API and implementation * Alexandra Buzila - bug 478620 + * Martin Fleck - bug 507177 *******************************************************************************/ package org.eclipse.emf.compare.tests.utils; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; - -import java.util.Iterator; -import java.util.Set; - import org.eclipse.emf.compare.graph.IGraph; -import org.eclipse.emf.compare.graph.PruningIterator; import org.eclipse.emf.compare.internal.utils.Graph; -import org.junit.Test; /** - * We will use this to test the utility methods exposed by the {@link Graph}. + * We will use this to test the utility methods exposed by the {@link Graph}. The test methods are inherited + * from {@link AbstractGraphTest}. * * @author <a href="mailto:axel.richard@obeo.fr">Axel Richard</a> */ -@SuppressWarnings("nls") -public class GraphTest { - - @Test - public void testBuildSubGraph() { - IGraph<String> graph = new Graph<String>(); - /** - * <pre> - * Add the following graph: - * e f - * | | - * b c d - * \ | / - * \ | / - * --------- - * | - * a - * </pre> - */ - graph.addChildren("a", ImmutableSet.of("b", "c", "d")); - graph.addChildren("c", ImmutableSet.of("e")); - graph.addChildren("d", ImmutableSet.of("f")); - - Set<String> subgraph = graph.getSubgraphContaining("d", ImmutableSet.of("c")); - assertEquals(4, subgraph.size()); - assertTrue(subgraph.containsAll(Lists.newArrayList("a", "b", "d", "f"))); - } - - /* - * Just to avoid infinite loop in prune. - */ - @Test - public void testPrune() { - IGraph<String> graph = new Graph<String>(); - /** - * <pre> - * Add the following graph: - * c-\ - * | | - * b-/ - * | - * a - * </pre> - */ - graph.addChildren("a", ImmutableSet.of("b")); - graph.addChildren("b", ImmutableSet.of("c")); - graph.addChildren("c", ImmutableSet.of("b")); - PruningIterator<String> iterator = graph.breadthFirstIterator(); - while (iterator.hasNext()) { - iterator.next(); - iterator.prune(); - } - } - - @Test - public void testBreadthFirstIteration() { - IGraph<String> graph = new Graph<String>(); - /** - * <pre> - * With the following Graph: - * - * A I J - * / \ / / \ - * B C G K L - * / / \ / \ / \ - * D E F H M N - * - * We expect our iteration to go in the following order: - * three first items, in unspecified order : A, I, J - * next five, in unspecified order : B, C, G, K, L - * finally, still in unspecified order : D, E, F, H, M, N - * </pre> - */ - graph.addChildren("A", ImmutableSet.of("B", "C")); - graph.addChildren("B", ImmutableSet.of("D")); - graph.addChildren("C", ImmutableSet.of("E", "F")); - graph.addChildren("I", ImmutableSet.of("G")); - graph.addChildren("G", ImmutableSet.of("F", "H")); - graph.addChildren("J", ImmutableSet.of("K", "L")); - graph.addChildren("L", ImmutableSet.of("M", "N")); - - Set<String> firstThree = Sets.newHashSet("A", "I", "J"); - Set<String> nextFive = Sets.newHashSet("B", "C", "G", "K", "L"); - Set<String> finalSix = Sets.newHashSet("D", "E", "F", "H", "M", "N"); - - PruningIterator<String> iterator = graph.breadthFirstIterator(); - assertTrue(firstThree.remove(iterator.next())); - assertTrue(firstThree.remove(iterator.next())); - assertTrue(firstThree.remove(iterator.next())); - assertTrue(firstThree.isEmpty()); - - assertTrue(nextFive.remove(iterator.next())); - assertTrue(nextFive.remove(iterator.next())); - assertTrue(nextFive.remove(iterator.next())); - assertTrue(nextFive.remove(iterator.next())); - assertTrue(nextFive.remove(iterator.next())); - assertTrue(nextFive.isEmpty()); - - assertTrue(finalSix.remove(iterator.next())); - assertTrue(finalSix.remove(iterator.next())); - assertTrue(finalSix.remove(iterator.next())); - assertTrue(finalSix.remove(iterator.next())); - assertTrue(finalSix.remove(iterator.next())); - assertTrue(finalSix.remove(iterator.next())); - assertTrue(finalSix.isEmpty()); - assertFalse(iterator.hasNext()); - } - - @Test - public void testTreeIteration_1() { - IGraph<String> graph = getAcyclicGraph(); - - Iterator<String> iteratorOnA = graph.depthFirstIterator("A"); - assertEquals("A", iteratorOnA.next()); - assertEquals("B", iteratorOnA.next()); - assertEquals("D", iteratorOnA.next()); - assertEquals("C", iteratorOnA.next()); - assertEquals("E", iteratorOnA.next()); - assertEquals("F", iteratorOnA.next()); - assertFalse(iteratorOnA.hasNext()); - } - - @Test - public void testTreeIteration_2() { - IGraph<String> graph = getAcyclicGraph(); - - Iterator<String> iteratorOnC = graph.depthFirstIterator("C"); - assertEquals("C", iteratorOnC.next()); - assertEquals("E", iteratorOnC.next()); - assertEquals("F", iteratorOnC.next()); - assertFalse(iteratorOnC.hasNext()); - } - - @Test - public void testTreeIteration_3() { - IGraph<String> graph = getAcyclicGraph(); - - Iterator<String> iteratorOnI = graph.depthFirstIterator("I"); - assertEquals("I", iteratorOnI.next()); - assertEquals("G", iteratorOnI.next()); - assertEquals("F", iteratorOnI.next()); - assertEquals("H", iteratorOnI.next()); - assertFalse(iteratorOnI.hasNext()); - } - - @Test - public void testTreeIteration_4() { - IGraph<String> graph = getAcyclicGraph(); - - Iterator<String> iteratorOnJ = graph.depthFirstIterator("J"); - assertEquals("J", iteratorOnJ.next()); - assertEquals("K", iteratorOnJ.next()); - assertEquals("L", iteratorOnJ.next()); - assertEquals("M", iteratorOnJ.next()); - assertEquals("N", iteratorOnJ.next()); - assertFalse(iteratorOnJ.hasNext()); - } - - @Test - public void testDepthIterationWithCycles_1() { - IGraph<String> graph = getGraphWithCycles(); - - Iterator<String> iteratorOnA = graph.depthFirstIterator("A"); - assertEquals("A", iteratorOnA.next()); - assertEquals("B", iteratorOnA.next()); - assertEquals("D", iteratorOnA.next()); - assertEquals("E", iteratorOnA.next()); - assertEquals("C", iteratorOnA.next()); - assertEquals("F", iteratorOnA.next()); - assertEquals("H", iteratorOnA.next()); - - assertFalse(iteratorOnA.hasNext()); - } - - @Test - public void testDepthIterationWithCycles_2() { - IGraph<String> graph = getGraphWithCycles(); +public class GraphTest extends AbstractGraphTest<String> { - Iterator<String> iteratorOnC = graph.depthFirstIterator("C"); - assertEquals("C", iteratorOnC.next()); - assertEquals("A", iteratorOnC.next()); - assertEquals("B", iteratorOnC.next()); - assertEquals("D", iteratorOnC.next()); - assertEquals("E", iteratorOnC.next()); - assertEquals("F", iteratorOnC.next()); - assertEquals("H", iteratorOnC.next()); - - assertFalse(iteratorOnC.hasNext()); - } - - @Test - public void testDepthIterationWithCycles_3() { - IGraph<String> graph = getGraphWithCycles(); - - Iterator<String> iteratorOnI = graph.depthFirstIterator("I"); - assertEquals("I", iteratorOnI.next()); - assertEquals("G", iteratorOnI.next()); - assertEquals("F", iteratorOnI.next()); - assertEquals("H", iteratorOnI.next()); - - assertFalse(iteratorOnI.hasNext()); - } - - @Test - public void testDepthIterationWithCycles_4() { - IGraph<String> graph = getGraphWithCycles(); - - Iterator<String> iteratorOnJ = graph.depthFirstIterator("J"); - assertEquals("J", iteratorOnJ.next()); - assertEquals("K", iteratorOnJ.next()); - assertEquals("M", iteratorOnJ.next()); - assertEquals("L", iteratorOnJ.next()); - assertEquals("N", iteratorOnJ.next()); - - assertFalse(iteratorOnJ.hasNext()); - } - - /** - * Test the BreadthFirstIterator with the following cyclic graph: - * - * <pre> - * A - * / \ - * B = C - * </pre> - */ - @Test - public void testBug503035_1() { - IGraph<String> graph = new Graph<String>(); - - graph.addChildren("A", ImmutableSet.of("B", "C")); - graph.addChildren("B", ImmutableSet.of("C")); - graph.addChildren("C", ImmutableSet.of("B")); - - Iterator<String> it = graph.breadthFirstIterator(); - assertTrue(it.hasNext()); - assertEquals("A", it.next()); - assertTrue(it.hasNext()); - assertEquals("B", it.next()); - assertTrue(it.hasNext()); - assertEquals("C", it.next()); - assertFalse(it.hasNext()); + @Override + protected IGraph<String> createGraph() { + return new Graph<String>(); } - /** - * Test the BreadthFirstIterator with the following cyclic graph: - * - * <pre> - * A - * / \ - * B = C - * / - * D - * </pre> - */ - @Test - public void testBug503035_2() { - IGraph<String> graph = new Graph<String>(); - - graph.addChildren("A", ImmutableSet.of("B", "C")); - graph.addChildren("B", ImmutableSet.of("D", "C")); - graph.addChildren("C", ImmutableSet.of("B")); - - Iterator<String> it = graph.breadthFirstIterator(); - assertTrue(it.hasNext()); - assertEquals("A", it.next()); - assertTrue(it.hasNext()); - assertEquals("B", it.next()); - assertTrue(it.hasNext()); - assertEquals("C", it.next()); - assertTrue(it.hasNext()); - assertEquals("D", it.next()); - assertFalse(it.hasNext()); - } - - /** - * Test the BreadthFirstIterator with the following cyclic graph: - * - * <pre> - * A B - * | | - * C = D - * </pre> - */ - @Test - public void testBug503035_3() { - IGraph<String> graph = new Graph<String>(); - - graph.addChildren("A", ImmutableSet.of("C")); - graph.addChildren("B", ImmutableSet.of("D")); - graph.addChildren("C", ImmutableSet.of("D")); - graph.addChildren("D", ImmutableSet.of("C")); - - Iterator<String> it = graph.breadthFirstIterator(); - assertTrue(it.hasNext()); - assertEquals("A", it.next()); - assertTrue(it.hasNext()); - assertEquals("B", it.next()); - assertTrue(it.hasNext()); - assertEquals("C", it.next()); - assertTrue(it.hasNext()); - assertEquals("D", it.next()); - assertFalse(it.hasNext()); - } - - /** - * Test the BreadthFirstIterator with the following cyclic graph: - * - * <pre> - * A - * /|\ - * / | \ - * B C D - * \\===// - * </pre> - */ - @Test - public void testBug503035_4() { - IGraph<String> graph = new Graph<String>(); - - graph.addChildren("A", ImmutableSet.of("B", "C", "D")); - graph.addChildren("B", ImmutableSet.of("D")); - graph.addChildren("D", ImmutableSet.of("B")); - - Iterator<String> it = graph.breadthFirstIterator(); - assertTrue(it.hasNext()); - assertEquals("A", it.next()); - assertTrue(it.hasNext()); - assertEquals("B", it.next()); - assertTrue(it.hasNext()); - assertEquals("C", it.next()); - assertTrue(it.hasNext()); - assertEquals("D", it.next()); - assertFalse(it.hasNext()); - } - - /** - * @return The following acyclic graph: - * - * <pre> - * A I J - * / \ / / \ - * B C G K L - * / / \ / \ / \ - * D E F H M N - * </pre> - */ - private IGraph<String> getAcyclicGraph() { - IGraph<String> graph = new Graph<String>(); - - graph.addChildren("A", ImmutableSet.of("B", "C")); - graph.addChildren("B", ImmutableSet.of("D")); - graph.addChildren("C", ImmutableSet.of("E", "F")); - graph.addChildren("I", ImmutableSet.of("G")); - graph.addChildren("G", ImmutableSet.of("F", "H")); - graph.addChildren("J", ImmutableSet.of("K", "L")); - graph.addChildren("L", ImmutableSet.of("M", "N")); - - return graph; - } - - /** - * @return The following cyclic graph: - * - * <pre> - * A I J - * / \\ / / \ - * B C G K L - * / / \ / \ \ // \ - * D - E F = H M N - * </pre> - */ - private IGraph<String> getGraphWithCycles() { - IGraph<String> graph = new Graph<String>(); - - graph.addChildren("A", ImmutableSet.of("B", "C")); - graph.addChildren("B", ImmutableSet.of("D")); - graph.addChildren("D", ImmutableSet.of("E")); - graph.addChildren("C", ImmutableSet.of("A", "E", "F")); - graph.addChildren("I", ImmutableSet.of("G")); - graph.addChildren("G", ImmutableSet.of("F", "H")); - graph.addChildren("J", ImmutableSet.of("K", "L")); - graph.addChildren("K", ImmutableSet.of("M")); - graph.addChildren("M", ImmutableSet.of("L")); - graph.addChildren("L", ImmutableSet.of("M", "N")); - graph.addChildren("F", ImmutableSet.of("H")); - graph.addChildren("H", ImmutableSet.of("F")); - - return graph; + @Override + protected String toType(String name) { + return name; } } diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.compare.uml2.tests/META-INF/MANIFEST.MF index f4db51e5a..90d87b705 100644 --- a/plugins/org.eclipse.emf.compare.uml2.tests/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.emf.compare.uml2.tests/META-INF/MANIFEST.MF @@ -33,5 +33,6 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.papyrus.sysml;bundle-version="[1.0.2,2.0.0)" Bundle-ActivationPolicy: lazy Import-Package: com.google.common.base;version="[11.0.0,16.0.0)", - com.google.common.collect;version="[11.0.0,16.0.0)" + com.google.common.collect;version="[11.0.0,16.0.0)", + org.eclipse.emf.compare.rcp Bundle-Activator: org.eclipse.emf.compare.uml2.profile.test.uml2comparetestprofile.provider.UML2CompareTestProfileEditPlugin$Implementation diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/AbstractUMLTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/AbstractUMLTest.java index 78388134c..cb89c0665 100644 --- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/AbstractUMLTest.java +++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/AbstractUMLTest.java @@ -9,12 +9,14 @@ * Obeo - initial API and implementation * Stefan Dirix - update priority value for UML merger * Philip Langer - bug 501864 + * Martin Fleck - bug 507177 */ package org.eclipse.emf.compare.uml2.tests; import static com.google.common.base.Predicates.instanceOf; import static com.google.common.base.Predicates.not; import static com.google.common.collect.Iterators.all; +import static org.eclipse.emf.compare.merge.AbstractMerger.SUB_DIFF_AWARE_OPTION; import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasDirectOrIndirectConflict; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -22,9 +24,12 @@ import static org.junit.Assert.assertTrue; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.regex.Pattern; import org.eclipse.emf.common.EMFPlugin; @@ -41,6 +46,7 @@ import org.eclipse.emf.compare.EMFCompare.Builder; import org.eclipse.emf.compare.ReferenceChange; import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.merge.IBatchMerger; +import org.eclipse.emf.compare.merge.IMergeOptionAware; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.postprocessor.IPostProcessor; import org.eclipse.emf.compare.postprocessor.PostProcessorDescriptorRegistryImpl; @@ -78,6 +84,9 @@ public abstract class AbstractUMLTest { private IMerger.Registry mergerRegistry; + /** Cached cascading options before the last time the filter was enabled or disabled. */ + private static final Map<IMergeOptionAware, Object> CACHED_OPTIONS = Maps.newHashMap(); + /** * Each sublass of AbstractUMLTest have to call this method in a @BeforeClass annotated method. This allow * each test to customize its context. @@ -292,4 +301,49 @@ public abstract class AbstractUMLTest { } } + + /** + * Enables the cascading filter by setting the filter option in all mergers to true. Any changes done by + * this method can be restored by calling {@link #restoreCascadingFilter()}. + */ + protected void enableCascadingFilter() { + setCascadingFilter(true); + } + + /** + * Disables the cascading filter by setting the filter option in all mergers to false. Any changes done by + * this method can be restored by calling {@link #restoreCascadingFilter()}. + */ + protected void disableCascadingFilter() { + setCascadingFilter(false); + } + + /** + * 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 + */ + private void setCascadingFilter(boolean enabled) { + for (IMergeOptionAware merger : Iterables.filter(mergerRegistry.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 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.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociationTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociationTest.java index 88ffc5c91..d7f874a06 100644 --- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociationTest.java +++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/association/AddAssociationTest.java @@ -7,11 +7,14 @@ * * Contributors: * Obeo - initial API and implementation + * Martin Fleck - bug 507177 *******************************************************************************/ package org.eclipse.emf.compare.uml2.tests.association; import static com.google.common.base.Predicates.and; import static com.google.common.base.Predicates.instanceOf; +import static org.eclipse.emf.compare.DifferenceKind.ADD; +import static org.eclipse.emf.compare.DifferenceKind.DELETE; import static org.eclipse.emf.compare.utils.EMFComparePredicates.added; import static org.eclipse.emf.compare.utils.EMFComparePredicates.addedToReference; import static org.eclipse.emf.compare.utils.EMFComparePredicates.changedReference; @@ -33,7 +36,6 @@ import java.util.regex.Pattern; import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.Diff; -import org.eclipse.emf.compare.DifferenceKind; import org.eclipse.emf.compare.postprocessor.IPostProcessor.Descriptor.Registry; import org.eclipse.emf.compare.tests.postprocess.data.TestPostProcessor; import org.eclipse.emf.compare.uml2.internal.AssociationChange; @@ -72,6 +74,20 @@ public class AddAssociationTest extends AbstractUMLTest { } @Test + public void testA10UseCaseFilter() throws IOException { + try { + enableCascadingFilter(); + final Resource left = input.getA1Left(); + final Resource right = input.getA1Right(); + + final Comparison comparison = compare(left, right); + testAB1(TestKind.ADD, comparison); + } finally { + restoreCascadingFilter(); + } + } + + @Test public void testMergeRtLA10UseCase() throws IOException { final Resource left = input.getA1Left(); final Resource right = input.getA1Right(); @@ -80,6 +96,19 @@ public class AddAssociationTest extends AbstractUMLTest { } @Test + public void testMergeRtLA10UseCaseFilter() throws IOException { + try { + enableCascadingFilter(); + final Resource left = input.getA1Left(); + final Resource right = input.getA1Right(); + + testMergeRightToLeft(left, right, null); + } finally { + restoreCascadingFilter(); + } + } + + @Test public void testMergeLtRA10UseCase() throws IOException { final Resource left = input.getA1Left(); final Resource right = input.getA1Right(); @@ -88,6 +117,19 @@ public class AddAssociationTest extends AbstractUMLTest { } @Test + public void testMergeLtRA10UseCaseFilter() throws IOException { + try { + enableCascadingFilter(); + final Resource left = input.getA1Left(); + final Resource right = input.getA1Right(); + + testMergeLeftToRight(left, right, null); + } finally { + restoreCascadingFilter(); + } + } + + @Test public void testA11UseCase() throws IOException { final Resource left = input.getA1Right(); final Resource right = input.getA1Left(); @@ -97,6 +139,20 @@ public class AddAssociationTest extends AbstractUMLTest { } @Test + public void testA11UseCaseFilter() throws IOException { + try { + enableCascadingFilter(); + final Resource left = input.getA1Right(); + final Resource right = input.getA1Left(); + + final Comparison comparison = compare(left, right); + testAB1(TestKind.DELETE, comparison); + } finally { + restoreCascadingFilter(); + } + } + + @Test public void testMergeRtLA11UseCase() throws IOException { final Resource left = input.getA1Right(); final Resource right = input.getA1Left(); @@ -105,6 +161,19 @@ public class AddAssociationTest extends AbstractUMLTest { } @Test + public void testMergeRtLA11UseCaseFilter() throws IOException { + try { + enableCascadingFilter(); + final Resource left = input.getA1Right(); + final Resource right = input.getA1Left(); + + testMergeRightToLeft(left, right, null); + } finally { + restoreCascadingFilter(); + } + } + + @Test public void testMergeLtRA11UseCase() throws IOException { final Resource left = input.getA1Right(); final Resource right = input.getA1Left(); @@ -113,6 +182,19 @@ public class AddAssociationTest extends AbstractUMLTest { } @Test + public void testMergeLtRA11UseCaseFilter() throws IOException { + try { + enableCascadingFilter(); + final Resource left = input.getA1Right(); + final Resource right = input.getA1Left(); + + testMergeLeftToRight(left, right, null); + } finally { + restoreCascadingFilter(); + } + } + + @Test public void testA10UseCase3way() throws IOException { final Resource left = input.getA1Left(); final Resource right = input.getA1Right(); @@ -122,6 +204,20 @@ public class AddAssociationTest extends AbstractUMLTest { } @Test + public void testA10UseCase3wayFilter() throws IOException { + try { + enableCascadingFilter(); + final Resource left = input.getA1Left(); + final Resource right = input.getA1Right(); + + final Comparison comparison = compare(left, right, right); + testAB1(TestKind.ADD, comparison); + } finally { + restoreCascadingFilter(); + } + } + + @Test public void testMergeRtLA10UseCase3way() throws IOException { final Resource left = input.getA1Left(); final Resource right = input.getA1Right(); @@ -130,6 +226,19 @@ public class AddAssociationTest extends AbstractUMLTest { } @Test + public void testMergeRtLA10UseCase3wayFilter() throws IOException { + try { + enableCascadingFilter(); + final Resource left = input.getA1Left(); + final Resource right = input.getA1Right(); + + testMergeRightToLeft(left, right, right); + } finally { + restoreCascadingFilter(); + } + } + + @Test public void testMergeLtRA10UseCase3way() throws IOException { final Resource left = input.getA1Left(); final Resource right = input.getA1Right(); @@ -138,6 +247,19 @@ public class AddAssociationTest extends AbstractUMLTest { } @Test + public void testMergeLtRA10UseCase3wayFilter() throws IOException { + try { + enableCascadingFilter(); + final Resource left = input.getA1Left(); + final Resource right = input.getA1Right(); + + testMergeLeftToRight(left, right, right); + } finally { + restoreCascadingFilter(); + } + } + + @Test public void testA11UseCase3way() throws IOException { final Resource left = input.getA1Left(); final Resource right = input.getA1Right(); @@ -147,6 +269,20 @@ public class AddAssociationTest extends AbstractUMLTest { } @Test + public void testA11UseCase3wayFilter() throws IOException { + try { + enableCascadingFilter(); + final Resource left = input.getA1Left(); + final Resource right = input.getA1Right(); + + final Comparison comparison = compare(left, right, left); + testAB1(TestKind.DELETE, comparison); + } finally { + restoreCascadingFilter(); + } + } + + @Test public void testMergeRtLA11UseCase3way() throws IOException { final Resource left = input.getA1Left(); final Resource right = input.getA1Right(); @@ -155,6 +291,19 @@ public class AddAssociationTest extends AbstractUMLTest { } @Test + public void testMergeRtLA11UseCase3wayFilter() throws IOException { + try { + enableCascadingFilter(); + final Resource left = input.getA1Left(); + final Resource right = input.getA1Right(); + + testMergeRightToLeft(left, right, left); + } finally { + restoreCascadingFilter(); + } + } + + @Test public void testMergeLtRA11UseCase3way() throws IOException { final Resource left = input.getA1Left(); final Resource right = input.getA1Right(); @@ -162,6 +311,19 @@ public class AddAssociationTest extends AbstractUMLTest { testMergeLeftToRight(left, right, left); } + @Test + public void testMergeLtRA11UseCase3wayFilter() throws IOException { + try { + enableCascadingFilter(); + final Resource left = input.getA1Left(); + final Resource right = input.getA1Right(); + + testMergeLeftToRight(left, right, left); + } finally { + restoreCascadingFilter(); + } + } + private void testAB1(TestKind kind, final Comparison comparison) { final List<Diff> differences = comparison.getDifferences(); @@ -289,10 +451,10 @@ public class AddAssociationTest extends AbstractUMLTest { Diff addUMLAssociation = null; if (kind.equals(TestKind.ADD)) { addUMLAssociation = Iterators.find(differences.iterator(), - and(instanceOf(AssociationChange.class), ofKind(DifferenceKind.ADD))); + and(instanceOf(AssociationChange.class), ofKind(ADD))); } else { addUMLAssociation = Iterators.find(differences.iterator(), - and(instanceOf(AssociationChange.class), ofKind(DifferenceKind.DELETE))); + and(instanceOf(AssociationChange.class), ofKind(DELETE))); } assertNotNull(addUMLAssociation); assertEquals(15, addUMLAssociation.getRefinedBy().size()); @@ -394,19 +556,19 @@ public class AddAssociationTest extends AbstractUMLTest { } private static Predicate<? super Diff> addedLowerValueIn(final String qualifiedName) { - return and(ofKind(DifferenceKind.ADD), onEObject(qualifiedName), onFeature("lowerValue")); + return and(ofKind(ADD), onEObject(qualifiedName), onFeature("lowerValue")); } private static Predicate<? super Diff> addedUpperValueIn(final String qualifiedName) { - return and(ofKind(DifferenceKind.ADD), onEObject(qualifiedName), onFeature("upperValue")); + return and(ofKind(ADD), onEObject(qualifiedName), onFeature("upperValue")); } private static Predicate<? super Diff> removedLowerValueIn(final String qualifiedName) { - return and(ofKind(DifferenceKind.DELETE), onEObject(qualifiedName), onFeature("lowerValue")); + return and(ofKind(DELETE), onEObject(qualifiedName), onFeature("lowerValue")); } private static Predicate<? super Diff> removedUpperValueIn(final String qualifiedName) { - return and(ofKind(DifferenceKind.DELETE), onEObject(qualifiedName), onFeature("upperValue")); + return and(ofKind(DELETE), onEObject(qualifiedName), onFeature("upperValue")); } @Override diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsAssociationTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsAssociationTest.java index 8490bf1c3..e1c9cc409 100644 --- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsAssociationTest.java +++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsAssociationTest.java @@ -7,6 +7,7 @@ * * Contributors: * Obeo - initial API and implementation + * Martin Fleck - bug 507177: consider refinement in tests *******************************************************************************/ package org.eclipse.emf.compare.uml2.tests.implications; @@ -21,19 +22,20 @@ import static org.eclipse.emf.compare.utils.EMFComparePredicates.onFeature; import static org.eclipse.emf.compare.utils.EMFComparePredicates.removed; import static org.eclipse.emf.compare.utils.EMFComparePredicates.removedFromReference; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import com.google.common.base.Predicate; import com.google.common.collect.Iterators; import java.io.IOException; +import java.util.Arrays; import java.util.List; import org.eclipse.emf.common.util.BasicMonitor; import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.Diff; import org.eclipse.emf.compare.DifferenceKind; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.uml2.internal.AssociationChange; import org.eclipse.emf.compare.uml2.internal.MultiplicityElementChange; import org.eclipse.emf.compare.uml2.tests.AbstractUMLInputData; @@ -64,6 +66,7 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { private DiffsOfInterest getDiffs(Comparison comparison, TestKind kind) { final List<Diff> differences = comparison.getDifferences(); + Predicate<? super Diff> addAssociationDescription = null; Predicate<? super Diff> addNavigableOwnedEndClass1InAssociationDescription = null; Predicate<? super Diff> addNavigableOwnedEndClass2InAssociationDescription = null; @@ -170,6 +173,10 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { return diffs; } + private void assertNoDifferences(Comparison comparison) { + assertTrue(comparison.getDifferences().isEmpty()); + } + @Test public void testA10UseCase() throws IOException { final Resource left = input.getA1Left(); @@ -209,23 +216,14 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) - .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addNavigableOwnedEndClass1InAssociation), + new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) + // .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeAddNavigableOwnedEnd(comparison, diffs); - } - - private void checkMergeAddNavigableOwnedEnd(Comparison comparison, DiffsOfInterest diffs) { - assertEquals(NB_DIFFS - 6, comparison.getDifferences().size()); - assertNull(diffs.addNavigableOwnedEndClass1InAssociation); - assertNull(diffs.addOwnedEndClass1InAssociation); - assertNull(diffs.addMemberEndClass1InAssociation); - assertNull(diffs.addRefAssociationInPropertyClass1); - assertNull(diffs.addAssociation); - assertNull(diffs.addUMLAssociation); + assertNoDifferences(comparison); } @Test @@ -238,13 +236,14 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) - .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addNavigableOwnedEndClass1InAssociation), + new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) + // .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeAddNavigableOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -257,25 +256,14 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) - .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addNavigableOwnedEndClass1InAssociation), + new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) + // .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeDeleteNavigableOwnedEnd(comparison, diffs); - } - - private void checkMergeDeleteNavigableOwnedEnd(Comparison comparison, DiffsOfInterest diffs) { - // 7 diffs of interest + 2 MultiplicityElementChanges - assertEquals(NB_DIFFS - 9, comparison.getDifferences().size()); - assertNull(diffs.addNavigableOwnedEndClass1InAssociation); - assertNull(diffs.addOwnedEndClass1InAssociation); - assertNull(diffs.addMemberEndClass1InAssociation); - assertNull(diffs.addRefAssociationInPropertyClass1); - assertNull(diffs.addLiteralIntegerInClass1); - assertNull(diffs.addUnlimitedNaturalInClass1); - assertNull(diffs.addRefTypeInPropertyClass1); + assertNoDifferences(comparison); } @Test @@ -288,23 +276,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) - .copyLeftToRight(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addOwnedEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) + // .copyLeftToRight(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeAddOwnedEnd(comparison, diffs); - } - - private void checkMergeAddOwnedEnd(Comparison comparison, DiffsOfInterest diffs) { - assertEquals(NB_DIFFS - 6, comparison.getDifferences().size()); - assertNull(diffs.addOwnedEndClass1InAssociation); - assertNull(diffs.addMemberEndClass1InAssociation); - assertNull(diffs.addNavigableOwnedEndClass1InAssociation); - assertNull(diffs.addRefAssociationInPropertyClass1); - assertNull(diffs.addAssociation); - assertNull(diffs.addUMLAssociation); + assertNoDifferences(comparison); } @Test @@ -317,13 +295,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) - .copyLeftToRight(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addOwnedEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) + // .copyLeftToRight(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeAddOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -336,25 +314,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) - .copyLeftToRight(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addOwnedEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) + // .copyLeftToRight(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeDeleteOwnedEnd(comparison, diffs); - } - - private void checkMergeDeleteOwnedEnd(Comparison comparison, DiffsOfInterest diffs) { - // 7 diffs of interest+ 2 MultiplicityElementChanges - assertEquals(NB_DIFFS - 9, comparison.getDifferences().size()); - assertNull(diffs.addOwnedEndClass1InAssociation); - assertNull(diffs.addMemberEndClass1InAssociation); - assertNull(diffs.addRefAssociationInPropertyClass1); - assertNull(diffs.addNavigableOwnedEndClass1InAssociation); - assertNull(diffs.addLiteralIntegerInClass1); - assertNull(diffs.addUnlimitedNaturalInClass1); - assertNull(diffs.addRefTypeInPropertyClass1); + assertNoDifferences(comparison); } @Test @@ -367,23 +333,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) - .copyLeftToRight(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addMemberEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) + // .copyLeftToRight(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeAddMemberEnd(comparison, diffs); - } - - private void checkMergeAddMemberEnd(Comparison comparison, DiffsOfInterest diffs) { - assertEquals(NB_DIFFS - 6, comparison.getDifferences().size()); - assertNull(diffs.addMemberEndClass1InAssociation); - assertNull(diffs.addRefAssociationInPropertyClass1); - assertNull(diffs.addOwnedEndClass1InAssociation); - assertNull(diffs.addNavigableOwnedEndClass1InAssociation); - assertNull(diffs.addAssociation); - assertNull(diffs.addUMLAssociation); + assertNoDifferences(comparison); } @Test @@ -396,13 +352,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) - .copyLeftToRight(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addMemberEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) + // .copyLeftToRight(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeAddMemberEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -415,13 +371,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) - .copyLeftToRight(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addMemberEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) + // .copyLeftToRight(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeDeleteOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -434,13 +390,14 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) - .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addNavigableOwnedEndClass1InAssociation), + new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) + // .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeDeleteNavigableOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -453,13 +410,14 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) - .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addNavigableOwnedEndClass1InAssociation), + new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) + // .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeDeleteNavigableOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -472,13 +430,14 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) - .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addNavigableOwnedEndClass1InAssociation), + new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) + // .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeAddNavigableOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -491,13 +450,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) - .copyRightToLeft(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addOwnedEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) + // .copyRightToLeft(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeDeleteOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -510,13 +469,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) - .copyRightToLeft(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addOwnedEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) + // .copyRightToLeft(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeDeleteOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -529,13 +488,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) - .copyRightToLeft(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addOwnedEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) + // .copyRightToLeft(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeAddOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -548,13 +507,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) - .copyRightToLeft(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addMemberEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) + // .copyRightToLeft(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeDeleteOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -567,13 +526,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) - .copyRightToLeft(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addMemberEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) + // .copyRightToLeft(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeDeleteOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -586,13 +545,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) - .copyRightToLeft(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addMemberEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) + // .copyRightToLeft(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.ADD); - - checkMergeAddMemberEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -634,13 +593,14 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) - .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addNavigableOwnedEndClass1InAssociation), + new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) + // .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeDeleteNavigableOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -653,13 +613,14 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) - .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addNavigableOwnedEndClass1InAssociation), + new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) + // .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeDeleteNavigableOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -672,13 +633,14 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) - .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addNavigableOwnedEndClass1InAssociation), + new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) + // .copyLeftToRight(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeAddNavigableOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -691,13 +653,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) - .copyLeftToRight(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addOwnedEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) + // .copyLeftToRight(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeDeleteOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -710,13 +672,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) - .copyLeftToRight(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addOwnedEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) + // .copyLeftToRight(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeDeleteOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -729,13 +691,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) - .copyLeftToRight(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addOwnedEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) + // .copyLeftToRight(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeAddOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -748,13 +710,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) - .copyLeftToRight(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addMemberEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) + // .copyLeftToRight(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeDeleteOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -767,13 +729,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) - .copyLeftToRight(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addMemberEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) + // .copyLeftToRight(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeDeleteOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -786,13 +748,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) - .copyLeftToRight(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addMemberEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) + // .copyLeftToRight(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeAddMemberEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -805,13 +767,14 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) - .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addNavigableOwnedEndClass1InAssociation), + new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) + // .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeAddNavigableOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -824,13 +787,14 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) - .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addNavigableOwnedEndClass1InAssociation), + new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) + // .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeAddNavigableOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -843,13 +807,14 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) - .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addNavigableOwnedEndClass1InAssociation), + new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addNavigableOwnedEndClass1InAssociation) + // .copyRightToLeft(diffs.addNavigableOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeDeleteNavigableOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -862,13 +827,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) - .copyRightToLeft(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addOwnedEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) + // .copyRightToLeft(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeAddOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -881,13 +846,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) - .copyRightToLeft(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addOwnedEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) + // .copyRightToLeft(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeAddOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -900,13 +865,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) - .copyRightToLeft(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addOwnedEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addOwnedEndClass1InAssociation) + // .copyRightToLeft(diffs.addOwnedEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeDeleteOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -919,13 +884,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) - .copyRightToLeft(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addMemberEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) + // .copyRightToLeft(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeAddMemberEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -938,13 +903,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) - .copyRightToLeft(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addMemberEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) + // .copyRightToLeft(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeAddMemberEnd(comparison, diffs); + assertNoDifferences(comparison); } @Test @@ -957,13 +922,13 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) - .copyRightToLeft(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addMemberEndClass1InAssociation), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addMemberEndClass1InAssociation) + // .copyRightToLeft(diffs.addMemberEndClass1InAssociation, new BasicMonitor()); comparison = compare(left, right); - diffs = getDiffs(comparison, TestKind.DELETE); - - checkMergeDeleteOwnedEnd(comparison, diffs); + assertNoDifferences(comparison); } private void testAB1(TestKind kind, final Comparison comparison) { @@ -1013,7 +978,6 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { assertTrue(diffs.addMemberEndClass1InAssociation.getImpliedBy() .contains(diffs.addOwnedEndClass1InAssociation)); } - } @Override @@ -1021,21 +985,25 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { return input; } + @SuppressWarnings("unchecked") private static Predicate<? super Diff> addedLowerValueIn(final String qualifiedName) { return and(ofKind(DifferenceKind.ADD), onEObject(qualifiedName), onFeature("lowerValue"), refinesMultiplicityElementChange()); } + @SuppressWarnings("unchecked") private static Predicate<? super Diff> addedUpperValueIn(final String qualifiedName) { return and(ofKind(DifferenceKind.ADD), onEObject(qualifiedName), onFeature("upperValue"), refinesMultiplicityElementChange()); } + @SuppressWarnings("unchecked") private static Predicate<? super Diff> removedLowerValueIn(final String qualifiedName) { return and(ofKind(DifferenceKind.DELETE), onEObject(qualifiedName), onFeature("lowerValue"), refinesMultiplicityElementChange()); } + @SuppressWarnings("unchecked") private static Predicate<? super Diff> removedUpperValueIn(final String qualifiedName) { return and(ofKind(DifferenceKind.DELETE), onEObject(qualifiedName), onFeature("upperValue"), refinesMultiplicityElementChange()); @@ -1050,6 +1018,7 @@ public class ImplicationsAssociationTest extends AbstractUMLTest { }; } + @SuppressWarnings("unused") private class DiffsOfInterest { public Diff addAssociation; diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsInterfaceRealizationTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsInterfaceRealizationTest.java index 786fef785..632aa1318 100644 --- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsInterfaceRealizationTest.java +++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsInterfaceRealizationTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2014 Obeo. + * Copyright (c) 2012, 2016 Obeo. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * Obeo - initial API and implementation + * Martin Fleck - bug 507177: adapt for refinement behavior *******************************************************************************/ package org.eclipse.emf.compare.uml2.tests.implications; @@ -16,6 +17,7 @@ import static org.eclipse.emf.compare.utils.EMFComparePredicates.addedToReferenc import static org.eclipse.emf.compare.utils.EMFComparePredicates.changedReference; import static org.eclipse.emf.compare.utils.EMFComparePredicates.removedFromReference; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -23,11 +25,13 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterators; import java.io.IOException; +import java.util.Arrays; import java.util.List; import org.eclipse.emf.common.util.BasicMonitor; import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.Diff; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.uml2.internal.DirectedRelationshipChange; import org.eclipse.emf.compare.uml2.tests.AbstractUMLInputData; import org.eclipse.emf.compare.uml2.tests.AbstractUMLTest; @@ -43,6 +47,8 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { private static final int NB_DIFFS = 9; + private static final int NB_INTERFACE_REALIZATION_DIFFS = 5; + private ImplicationsInputData input = new ImplicationsInputData(); @BeforeClass @@ -65,8 +71,6 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { Predicate<? super Diff> addSubstitutionDescription = null; Predicate<? super Diff> addClientInSubstitutionDescription = null; Predicate<? super Diff> addSupplierInSubstitutionDescription = null; - Predicate<? super Diff> addUMLInterfaceRealizationDescription = null; - Predicate<? super Diff> addUMLSubstitutionDescription = null; if (kind.equals(TestKind.DELETE)) { addInterfaceRealizationDescription = removedFromReference("model.Class0", "interfaceRealization", @@ -164,20 +168,32 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) - .copyLeftToRight(diffs.addClientInInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addClientInInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) + // .copyLeftToRight(diffs.addClientInInterfaceRealization, new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.ADD); - checkMergeAddClientInInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } - private void checkMergeAddClientInInterfaceRealization(Comparison comparison, DiffsOfInterest diffs) { - assertEquals(NB_DIFFS - 3, comparison.getDifferences().size()); - assertNull(diffs.addClientInInterfaceRealization); - assertNull(diffs.addInterfaceRealization); + private void checkMergeInterfaceRealization(Comparison comparison, DiffsOfInterest diffs) { + assertEquals(NB_DIFFS - NB_INTERFACE_REALIZATION_DIFFS, comparison.getDifferences().size()); + + // interface realization refinement has been merged together as a whole, diffs are null assertNull(diffs.addUMLInterfaceRealization); + assertNull(diffs.addInterfaceRealization); + assertNull(diffs.addClientInInterfaceRealization); + assertNull(diffs.addContractInInterfaceRealization); + assertNull(diffs.addSupplierInInterfaceRealization); + + // substitution not merged as a whole, diffs are still set + assertNotNull(diffs.addUMLSubstitution); + assertNotNull(diffs.addSubstitution); + assertNotNull(diffs.addClientInSubstitution); + assertNotNull(diffs.addSupplierInSubstitution); } @Test @@ -190,13 +206,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) - .copyLeftToRight(diffs.addClientInInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addClientInInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) + // .copyLeftToRight(diffs.addClientInInterfaceRealization, new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.ADD); - checkMergeAddClientInInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -209,22 +227,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) - .copyLeftToRight(diffs.addClientInInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addClientInInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) + // .copyLeftToRight(diffs.addClientInInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, left); diffs = getDiffs(comparison, TestKind.ADD); - checkMergeDeleteClientInInterfaceRealization(comparison, diffs); - } - - private void checkMergeDeleteClientInInterfaceRealization(Comparison comparison, DiffsOfInterest diffs) { - assertEquals(NB_DIFFS - 5, comparison.getDifferences().size()); - assertNull(diffs.addClientInInterfaceRealization); - assertNull(diffs.addInterfaceRealization); - assertNull(diffs.addSupplierInInterfaceRealization); - assertNull(diffs.addContractInInterfaceRealization); - assertNull(diffs.addUMLInterfaceRealization); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -237,20 +248,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) - .copyLeftToRight(diffs.addInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) + // .copyLeftToRight(diffs.addInterfaceRealization, new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.ADD); - checkMergeAddInterfaceRealization(comparison, diffs); - } - - private void checkMergeAddInterfaceRealization(Comparison comparison, DiffsOfInterest diffs) { - assertEquals(NB_DIFFS - 3, comparison.getDifferences().size()); - assertNull(diffs.addInterfaceRealization); - assertNull(diffs.addClientInInterfaceRealization); - assertNull(diffs.addUMLInterfaceRealization); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -263,13 +269,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) - .copyLeftToRight(diffs.addInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) + // .copyLeftToRight(diffs.addInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, right); diffs = getDiffs(comparison, TestKind.ADD); - checkMergeAddInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -282,22 +290,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) - .copyLeftToRight(diffs.addInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) + // .copyLeftToRight(diffs.addInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, left); diffs = getDiffs(comparison, TestKind.ADD); - checkMergeDeleteInterfaceRealization(comparison, diffs); - } - - private void checkMergeDeleteInterfaceRealization(Comparison comparison, DiffsOfInterest diffs) { - assertEquals(NB_DIFFS - 5, comparison.getDifferences().size()); - assertNull(diffs.addInterfaceRealization); - assertNull(diffs.addClientInInterfaceRealization); - assertNull(diffs.addSupplierInInterfaceRealization); - assertNull(diffs.addContractInInterfaceRealization); - assertNull(diffs.addUMLInterfaceRealization); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -310,13 +311,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) - .copyRightToLeft(diffs.addClientInInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addClientInInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) + // .copyRightToLeft(diffs.addClientInInterfaceRealization, new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.ADD); - checkMergeDeleteClientInInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -329,13 +332,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) - .copyRightToLeft(diffs.addClientInInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addClientInInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) + // .copyRightToLeft(diffs.addClientInInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, right); diffs = getDiffs(comparison, TestKind.ADD); - checkMergeDeleteClientInInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -348,13 +353,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) - .copyRightToLeft(diffs.addClientInInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addClientInInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) + // .copyRightToLeft(diffs.addClientInInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, left); diffs = getDiffs(comparison, TestKind.ADD); - checkMergeAddClientInInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -367,13 +374,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) - .copyRightToLeft(diffs.addInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) + // .copyRightToLeft(diffs.addInterfaceRealization, new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.ADD); - checkMergeDeleteInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -386,13 +395,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) - .copyRightToLeft(diffs.addInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) + // .copyRightToLeft(diffs.addInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, right); diffs = getDiffs(comparison, TestKind.ADD); - checkMergeDeleteInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -405,13 +416,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) - .copyRightToLeft(diffs.addInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) + // .copyRightToLeft(diffs.addInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, left); diffs = getDiffs(comparison, TestKind.ADD); - checkMergeAddInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -453,13 +466,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) - .copyLeftToRight(diffs.addClientInInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addClientInInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) + // .copyLeftToRight(diffs.addClientInInterfaceRealization, new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.DELETE); - checkMergeDeleteClientInInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -472,13 +487,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) - .copyLeftToRight(diffs.addClientInInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addClientInInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) + // .copyLeftToRight(diffs.addClientInInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, right); diffs = getDiffs(comparison, TestKind.DELETE); - checkMergeDeleteClientInInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -491,13 +508,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) - .copyLeftToRight(diffs.addClientInInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addClientInInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) + // .copyLeftToRight(diffs.addClientInInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, left); diffs = getDiffs(comparison, TestKind.DELETE); - checkMergeAddClientInInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -510,13 +529,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) - .copyLeftToRight(diffs.addInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) + // .copyLeftToRight(diffs.addInterfaceRealization, new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.DELETE); - checkMergeDeleteInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -529,13 +550,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) - .copyLeftToRight(diffs.addInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) + // .copyLeftToRight(diffs.addInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, right); diffs = getDiffs(comparison, TestKind.DELETE); - checkMergeDeleteInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -548,13 +571,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) - .copyLeftToRight(diffs.addInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) + // .copyLeftToRight(diffs.addInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, left); diffs = getDiffs(comparison, TestKind.DELETE); - checkMergeAddInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -567,13 +592,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) - .copyRightToLeft(diffs.addClientInInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addClientInInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) + // .copyRightToLeft(diffs.addClientInInterfaceRealization, new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.DELETE); - checkMergeAddClientInInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -586,13 +613,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) - .copyRightToLeft(diffs.addClientInInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addClientInInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) + // .copyRightToLeft(diffs.addClientInInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, right); diffs = getDiffs(comparison, TestKind.DELETE); - checkMergeAddClientInInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -605,13 +634,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) - .copyRightToLeft(diffs.addClientInInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addClientInInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addClientInInterfaceRealization) + // .copyRightToLeft(diffs.addClientInInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, left); diffs = getDiffs(comparison, TestKind.DELETE); - checkMergeDeleteClientInInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -624,13 +655,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) - .copyRightToLeft(diffs.addInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) + // .copyRightToLeft(diffs.addInterfaceRealization, new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.DELETE); - checkMergeAddInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -643,13 +676,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) - .copyRightToLeft(diffs.addInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) + // .copyRightToLeft(diffs.addInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, right); diffs = getDiffs(comparison, TestKind.DELETE); - checkMergeAddInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } @Test @@ -662,13 +697,15 @@ public class ImplicationsInterfaceRealizationTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) - .copyRightToLeft(diffs.addInterfaceRealization, new BasicMonitor()); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllLeftToRight(Arrays.asList(diffs.addInterfaceRealization), new BasicMonitor()); + // getMergerRegistry().getHighestRankingMerger(diffs.addInterfaceRealization) + // .copyRightToLeft(diffs.addInterfaceRealization, new BasicMonitor()); - comparison = compare(left, right); + comparison = compare(left, right, left); diffs = getDiffs(comparison, TestKind.DELETE); - checkMergeDeleteInterfaceRealization(comparison, diffs); + checkMergeInterfaceRealization(comparison, diffs); } private void testAB1(TestKind kind, final Comparison comparison) { diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsTransitionTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsTransitionTest.java index 24efb6b83..ce66f7385 100644 --- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsTransitionTest.java +++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/implications/ImplicationsTransitionTest.java @@ -23,11 +23,13 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterators; import java.io.IOException; +import java.util.Arrays; import java.util.List; import org.eclipse.emf.common.util.BasicMonitor; import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.Diff; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.uml2.tests.AbstractUMLInputData; import org.eclipse.emf.compare.uml2.tests.AbstractUMLTest; import org.eclipse.emf.compare.uml2.tests.implications.data.ImplicationsInputData; @@ -126,8 +128,8 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition) - .copyLeftToRight(diffs.addPrecondition, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addPrecondition), + new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.ADD); @@ -153,8 +155,8 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition) - .copyLeftToRight(diffs.addPrecondition, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addPrecondition), + new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.ADD); @@ -172,8 +174,8 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition) - .copyLeftToRight(diffs.addPrecondition, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addPrecondition), + new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.ADD); @@ -198,7 +200,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyLeftToRight(diffs.addGuard, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addGuard), new BasicMonitor()); comparison = compare(left, right); @@ -225,7 +227,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyLeftToRight(diffs.addGuard, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addGuard), new BasicMonitor()); comparison = compare(left, right); @@ -244,7 +246,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyLeftToRight(diffs.addGuard, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addGuard), new BasicMonitor()); comparison = compare(left, right); @@ -270,7 +272,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyLeftToRight(diffs.addOwnedRule, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addOwnedRule), new BasicMonitor()); comparison = compare(left, right); @@ -297,7 +299,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyLeftToRight(diffs.addOwnedRule, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addOwnedRule), new BasicMonitor()); comparison = compare(left, right); @@ -316,7 +318,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyLeftToRight(diffs.addOwnedRule, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addOwnedRule), new BasicMonitor()); comparison = compare(left, right); @@ -342,8 +344,8 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition) - .copyRightToLeft(diffs.addPrecondition, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addPrecondition), + new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.ADD); @@ -361,8 +363,8 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition) - .copyRightToLeft(diffs.addPrecondition, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addPrecondition), + new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.ADD); @@ -380,8 +382,8 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition) - .copyRightToLeft(diffs.addPrecondition, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addPrecondition), + new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.ADD); @@ -399,7 +401,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyRightToLeft(diffs.addGuard, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addGuard), new BasicMonitor()); comparison = compare(left, right); @@ -418,7 +420,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyRightToLeft(diffs.addGuard, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addGuard), new BasicMonitor()); comparison = compare(left, right); @@ -437,7 +439,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyRightToLeft(diffs.addGuard, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addGuard), new BasicMonitor()); comparison = compare(left, right); @@ -456,7 +458,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyRightToLeft(diffs.addOwnedRule, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addOwnedRule), new BasicMonitor()); comparison = compare(left, right); @@ -475,7 +477,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyRightToLeft(diffs.addOwnedRule, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addOwnedRule), new BasicMonitor()); comparison = compare(left, right); @@ -494,7 +496,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.ADD); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyRightToLeft(diffs.addOwnedRule, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addOwnedRule), new BasicMonitor()); comparison = compare(left, right); @@ -542,8 +544,8 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition) - .copyLeftToRight(diffs.addPrecondition, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addPrecondition), + new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.DELETE); @@ -561,8 +563,8 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition) - .copyLeftToRight(diffs.addPrecondition, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addPrecondition), + new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.DELETE); @@ -580,8 +582,8 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition) - .copyLeftToRight(diffs.addPrecondition, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addPrecondition), + new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.DELETE); @@ -599,7 +601,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyLeftToRight(diffs.addGuard, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addGuard), new BasicMonitor()); comparison = compare(left, right); @@ -618,7 +620,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyLeftToRight(diffs.addGuard, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addGuard), new BasicMonitor()); comparison = compare(left, right); @@ -637,7 +639,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyLeftToRight(diffs.addGuard, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addGuard), new BasicMonitor()); comparison = compare(left, right); @@ -656,7 +658,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyLeftToRight(diffs.addOwnedRule, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addOwnedRule), new BasicMonitor()); comparison = compare(left, right); @@ -675,7 +677,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyLeftToRight(diffs.addOwnedRule, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addOwnedRule), new BasicMonitor()); comparison = compare(left, right); @@ -694,7 +696,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyLeftToRight(diffs.addOwnedRule, + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diffs.addOwnedRule), new BasicMonitor()); comparison = compare(left, right); @@ -713,8 +715,8 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition) - .copyRightToLeft(diffs.addPrecondition, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addPrecondition), + new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.DELETE); @@ -732,8 +734,8 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition) - .copyRightToLeft(diffs.addPrecondition, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addPrecondition), + new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.DELETE); @@ -751,8 +753,8 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addPrecondition) - .copyRightToLeft(diffs.addPrecondition, new BasicMonitor()); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addPrecondition), + new BasicMonitor()); comparison = compare(left, right); diffs = getDiffs(comparison, TestKind.DELETE); @@ -770,7 +772,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyRightToLeft(diffs.addGuard, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addGuard), new BasicMonitor()); comparison = compare(left, right); @@ -789,7 +791,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyRightToLeft(diffs.addGuard, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addGuard), new BasicMonitor()); comparison = compare(left, right); @@ -808,7 +810,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addGuard).copyRightToLeft(diffs.addGuard, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addGuard), new BasicMonitor()); comparison = compare(left, right); @@ -827,7 +829,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyRightToLeft(diffs.addOwnedRule, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addOwnedRule), new BasicMonitor()); comparison = compare(left, right); @@ -846,7 +848,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyRightToLeft(diffs.addOwnedRule, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addOwnedRule), new BasicMonitor()); comparison = compare(left, right); @@ -865,7 +867,7 @@ public class ImplicationsTransitionTest extends AbstractUMLTest { DiffsOfInterest diffs = getDiffs(comparison, TestKind.DELETE); // ** MERGE ** - getMergerRegistry().getHighestRankingMerger(diffs.addOwnedRule).copyRightToLeft(diffs.addOwnedRule, + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diffs.addOwnedRule), new BasicMonitor()); comparison = compare(left, right); diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/merge/MergeDiffInvolvingRefineDiffTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/merge/MergeDiffInvolvingRefineDiffTest.java index 85bd66a04..a041cc3a7 100644 --- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/merge/MergeDiffInvolvingRefineDiffTest.java +++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/merge/MergeDiffInvolvingRefineDiffTest.java @@ -18,12 +18,13 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterators; import java.io.IOException; +import java.util.Arrays; +import org.eclipse.emf.common.util.BasicMonitor; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.Diff; -import org.eclipse.emf.compare.merge.AbstractMerger; -import org.eclipse.emf.compare.merge.IMergeOptionAware; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.scope.DefaultComparisonScope; import org.eclipse.emf.compare.scope.IComparisonScope; @@ -34,6 +35,7 @@ import org.eclipse.emf.compare.uml2.tests.merge.data.DiffInvolvingRefineDiffInpu import org.eclipse.emf.ecore.resource.Resource; import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; @SuppressWarnings("nls") @@ -57,6 +59,7 @@ public class MergeDiffInvolvingRefineDiffTest extends AbstractUMLTest { } @Test + @Ignore("Mergers should not be aware of the cascading filter.") public void testMergeRightToLeftWithSubDiffsAwareOption() throws IOException { final Resource left = input.getLeft(); final Resource right = input.getRight(); @@ -74,12 +77,14 @@ public class MergeDiffInvolvingRefineDiffTest extends AbstractUMLTest { "ownedConnector", "SysMLmodel.InternalBlock.Block1.Connector2"); final Diff diff = Iterators.find(differences.iterator(), removedFromReference); - IMerger merger = registry.getHighestRankingMerger(diff); - if (merger instanceof IMergeOptionAware) { - ((IMergeOptionAware)merger).getMergeOptions().put(AbstractMerger.SUB_DIFF_AWARE_OPTION, - Boolean.TRUE); - } - merger.copyRightToLeft(diff, null); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); + // IMerger merger = registry.getHighestRankingMerger(diff); + // if (merger instanceof IMergeOptionAware) { + // ((IMergeOptionAware)merger).getMergeOptions().put(AbstractMerger.SUB_DIFF_AWARE_OPTION, + // Boolean.TRUE); + // } + // merger.copyRightToLeft(diff, null); final Comparison comparisonAfter = getCompare().compare(scope); // The subdiffs are merged with the selected diff (and the dependencies of these subdiffs) @@ -105,12 +110,14 @@ public class MergeDiffInvolvingRefineDiffTest extends AbstractUMLTest { "ownedConnector", "SysMLmodel.InternalBlock.Block1.Connector2"); final Diff diff = Iterators.find(differences.iterator(), removedFromReference); - IMerger merger = registry.getHighestRankingMerger(diff); - if (merger instanceof IMergeOptionAware) { - ((IMergeOptionAware)merger).getMergeOptions().put(AbstractMerger.SUB_DIFF_AWARE_OPTION, - Boolean.FALSE); - } - merger.copyRightToLeft(diff, null); + BatchMerger bm = new BatchMerger(getMergerRegistry()); + bm.copyAllRightToLeft(Arrays.asList(diff), new BasicMonitor()); + // IMerger merger = registry.getHighestRankingMerger(diff); + // if (merger instanceof IMergeOptionAware) { + // ((IMergeOptionAware)merger).getMergeOptions().put(AbstractMerger.SUB_DIFF_AWARE_OPTION, + // Boolean.FALSE); + // } + // merger.copyRightToLeft(diff, null); final Comparison comparisonAfter = getCompare().compare(scope); // The subdiffs are not merge, only the selected diff diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/message/bug507177/AddMessageSubDiffTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/message/bug507177/AddMessageSubDiffTest.java new file mode 100644 index 000000000..2632f1af4 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/message/bug507177/AddMessageSubDiffTest.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * 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: + * Martin Fleck - initial API and implementation + *******************************************************************************/ +package org.eclipse.emf.compare.uml2.tests.message.bug507177; + +import static org.eclipse.emf.compare.merge.AbstractMerger.SUB_DIFF_AWARE_OPTION; + +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; + +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.emf.common.util.BasicMonitor; +import org.eclipse.emf.compare.Comparison; +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.merge.BatchMerger; +import org.eclipse.emf.compare.merge.IBatchMerger; +import org.eclipse.emf.compare.merge.IMergeOptionAware; +import org.eclipse.emf.compare.merge.IMerger; +import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin; +import org.junit.runner.RunWith; + +/** + * Tests that equivalences are handled correctly when a message is added to an interaction. + * + * @author <a href="mailto:mfleck@eclipsesource.com">Martin Fleck</a> + */ +@RunWith(RuntimeTestRunner.class) +public class AddMessageSubDiffTest { + private static final IMerger.Registry MERGER_REGISTRY = EMFCompareRCPPlugin.getDefault() + .getMergerRegistry(); + + private static final Map<IMergeOptionAware, Object> CACHED_OPTIONS = Maps.newHashMap(); + + public void enableCascadingFilter() { + setCascadingFilter(true); + } + + public void disableCascadingFilter() { + setCascadingFilter(false); + } + + public 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)); + } + } + + public 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()); + } + } + + /** + * Test that equivalent diffs are not merged on both sides when sub-diffs are considered during the merge + * process, i.e., the cascading filter is enabled. In this test case, a single message is added. + * + * @param comparison + */ + @Compare(left = "data/left.uml", right = "data/right.uml") + public void testNoDuplicateAddition(final Comparison comparison) { + try { + enableCascadingFilter(); + final IBatchMerger merger = new BatchMerger(MERGER_REGISTRY); + merger.copyAllLeftToRight(comparison.getDifferences(), new BasicMonitor()); + // if no exception is thrown during merge, we are happy + } finally { + restoreCascadingFilter(); + } + } + +} diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/message/bug507177/data/left.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/message/bug507177/data/left.uml new file mode 100644 index 000000000..8566b68b4 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/message/bug507177/data/left.uml @@ -0,0 +1,18 @@ +<?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="_dGlfkLCUEeaDmogxouGepA" name="RootElement"> + <packagedElement xmi:type="uml:Interaction" xmi:id="_fZ4-8LCUEeaDmogxouGepA" name="InteractionA"> + <ownedParameter xmi:type="uml:Parameter" xmi:id="_i49t4LCUEeaDmogxouGepA" name="ca" type="_qvI_8LCUEeaDmogxouGepA"/> + <ownedParameter xmi:type="uml:Parameter" xmi:id="_U1-e0LCVEeaDmogxouGepA" name="cb" type="_SZZHoLCVEeaDmogxouGepA"/> + <lifeline xmi:type="uml:Lifeline" xmi:id="_kqbrgLCUEeaDmogxouGepA" name="LifelineCA" represents="_i49t4LCUEeaDmogxouGepA" coveredBy="_A4EJcLCWEeaDmogxouGepA"/> + <lifeline xmi:type="uml:Lifeline" xmi:id="_XCkSMLCVEeaDmogxouGepA" name="LifelineCB" represents="_U1-e0LCVEeaDmogxouGepA" coveredBy="_A4F-oLCWEeaDmogxouGepA"/> + <fragment xmi:type="uml:MessageOccurrenceSpecification" xmi:id="_A4EJcLCWEeaDmogxouGepA" name="SignalA_MessageSend" covered="_kqbrgLCUEeaDmogxouGepA" message="_A3-C0LCWEeaDmogxouGepA"/> + <fragment xmi:type="uml:MessageOccurrenceSpecification" xmi:id="_A4F-oLCWEeaDmogxouGepA" name="SignalA_MessageRecv" covered="_XCkSMLCVEeaDmogxouGepA" message="_A3-C0LCWEeaDmogxouGepA"/> + <message xmi:type="uml:Message" xmi:id="_A3-C0LCWEeaDmogxouGepA" name="SignalA_MessageA" messageSort="asynchSignal" receiveEvent="_A4F-oLCWEeaDmogxouGepA" sendEvent="_A4EJcLCWEeaDmogxouGepA" signature="_i6KyULCVEeaDmogxouGepA"/> + </packagedElement> + <packagedElement xmi:type="uml:Component" xmi:id="_qvI_8LCUEeaDmogxouGepA" name="ComponentA"/> + <packagedElement xmi:type="uml:Component" xmi:id="_SZZHoLCVEeaDmogxouGepA" name="ComponentB"/> + <packagedElement xmi:type="uml:Interface" xmi:id="_b33NMLCVEeaDmogxouGepA" name="InterfaceA"> + <nestedClassifier xmi:type="uml:Signal" xmi:id="_i6KyULCVEeaDmogxouGepA" name="SignalA"/> + <ownedReception xmi:type="uml:Reception" xmi:id="_l7EXgLCVEeaDmogxouGepA" name="SignalA" signal="_i6KyULCVEeaDmogxouGepA"/> + </packagedElement> +</uml:Model> diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/message/bug507177/data/right.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/message/bug507177/data/right.uml new file mode 100644 index 000000000..512c24663 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/message/bug507177/data/right.uml @@ -0,0 +1,15 @@ +<?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="_dGlfkLCUEeaDmogxouGepA" name="RootElement"> + <packagedElement xmi:type="uml:Interaction" xmi:id="_fZ4-8LCUEeaDmogxouGepA" name="InteractionA"> + <ownedParameter xmi:id="_i49t4LCUEeaDmogxouGepA" name="ca" type="_qvI_8LCUEeaDmogxouGepA"/> + <ownedParameter xmi:id="_U1-e0LCVEeaDmogxouGepA" name="cb" type="_SZZHoLCVEeaDmogxouGepA"/> + <lifeline xmi:id="_kqbrgLCUEeaDmogxouGepA" name="LifelineCA" represents="_i49t4LCUEeaDmogxouGepA"/> + <lifeline xmi:id="_XCkSMLCVEeaDmogxouGepA" name="LifelineCB" represents="_U1-e0LCVEeaDmogxouGepA"/> + </packagedElement> + <packagedElement xmi:type="uml:Component" xmi:id="_qvI_8LCUEeaDmogxouGepA" name="ComponentA"/> + <packagedElement xmi:type="uml:Component" xmi:id="_SZZHoLCVEeaDmogxouGepA" name="ComponentB"/> + <packagedElement xmi:type="uml:Interface" xmi:id="_b33NMLCVEeaDmogxouGepA" name="InterfaceA"> + <nestedClassifier xmi:type="uml:Signal" xmi:id="_i6KyULCVEeaDmogxouGepA" name="SignalA"/> + <ownedReception xmi:id="_l7EXgLCVEeaDmogxouGepA" name="SignalA" signal="_i6KyULCVEeaDmogxouGepA"/> + </packagedElement> +</uml:Model> diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/DanglingStereotypeApplicationTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/DanglingStereotypeApplicationTest.java index 252a73ef8..61e472cc0 100644 --- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/DanglingStereotypeApplicationTest.java +++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/DanglingStereotypeApplicationTest.java @@ -16,6 +16,7 @@ import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasState; import static org.junit.Assert.assertEquals; import java.io.IOException; +import java.util.Arrays; import java.util.Map; import org.eclipse.emf.common.EMFPlugin; @@ -24,6 +25,7 @@ import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.Diff; import org.eclipse.emf.compare.DifferenceState; import org.eclipse.emf.compare.ResourceAttachmentChange; +import org.eclipse.emf.compare.merge.BatchMerger; import org.eclipse.emf.compare.uml2.internal.DanglingStereotypeApplication; import org.eclipse.emf.compare.uml2.profile.test.uml2comparetestprofile.UML2CompareTestProfilePackage; import org.eclipse.emf.compare.uml2.tests.AbstractUMLInputData; @@ -160,7 +162,7 @@ public class DanglingStereotypeApplicationTest extends AbstractUMLProfileTest { Iterable<DanglingStereotypeApplication> danglings = filter(comparison.getDifferences(), DanglingStereotypeApplication.class); for (Diff diff : danglings) { - getMergerRegistry().getHighestRankingMerger(diff).copyLeftToRight(diff, null); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diff), null); } assertEquals(1, left.getContents().size()); assertEquals(1, right.getContents().size()); @@ -182,7 +184,7 @@ public class DanglingStereotypeApplicationTest extends AbstractUMLProfileTest { Iterable<DanglingStereotypeApplication> danglings = filter(comparison.getDifferences(), DanglingStereotypeApplication.class); for (Diff diff : danglings) { - getMergerRegistry().getHighestRankingMerger(diff).copyRightToLeft(diff, null); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diff), null); } assertEquals(2, left.getContents().size()); assertEquals(2, right.getContents().size()); @@ -205,7 +207,7 @@ public class DanglingStereotypeApplicationTest extends AbstractUMLProfileTest { Iterable<DanglingStereotypeApplication> danglings = filter(comparison.getDifferences(), DanglingStereotypeApplication.class); for (Diff diff : danglings) { - getMergerRegistry().getHighestRankingMerger(diff).copyLeftToRight(diff, null); + new BatchMerger(getMergerRegistry()).copyAllLeftToRight(Arrays.asList(diff), null); } assertEquals(1, left.getContents().size()); assertEquals(1, right.getContents().size()); @@ -229,7 +231,7 @@ public class DanglingStereotypeApplicationTest extends AbstractUMLProfileTest { Iterable<DanglingStereotypeApplication> danglings = filter(comparison.getDifferences(), DanglingStereotypeApplication.class); for (Diff diff : danglings) { - getMergerRegistry().getHighestRankingMerger(diff).copyRightToLeft(diff, null); + new BatchMerger(getMergerRegistry()).copyAllRightToLeft(Arrays.asList(diff), null); } assertEquals(2, left.getContents().size()); assertEquals(2, right.getContents().size()); diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/suite/AllTests.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/suite/AllTests.java index 5774a8526..8d790448d 100644 --- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/suite/AllTests.java +++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/suite/AllTests.java @@ -10,6 +10,7 @@ * Philip Langer - addition of OpaqueTest, ImplicationsInstanceSpecificationClassifiersTest * Stefan Dirix - addition of PseudoConflictTest * Martin Fleck - addition of RemoveStereotypeApplicationPseudoConflictTest + * Martin Fleck - addition of AddMessageSubDiffTest *******************************************************************************/ package org.eclipse.emf.compare.uml2.tests.suite; @@ -40,6 +41,7 @@ import org.eclipse.emf.compare.uml2.tests.merge.ExtensionMergeTest; import org.eclipse.emf.compare.uml2.tests.merge.InstanceSpecificationClassifiersMergeTest; import org.eclipse.emf.compare.uml2.tests.merge.MergeDiffInvolvingRefineDiffTest; import org.eclipse.emf.compare.uml2.tests.message.AddMessageTest; +import org.eclipse.emf.compare.uml2.tests.message.bug507177.AddMessageSubDiffTest; import org.eclipse.emf.compare.uml2.tests.multiplicitychanges.MultiplicityElementChangesTest; import org.eclipse.emf.compare.uml2.tests.nonreg.bug484576_pseudoconflicts.TestNonRegPseudoConflict_484576; import org.eclipse.emf.compare.uml2.tests.opaque.OpaqueElementBodyChangeDiffTest; @@ -82,7 +84,8 @@ import junit.textui.TestRunner; OpaqueElementBodyChangeDiffTest.class, OpaqueElementBodyChangeMergeTest.class, DanglingStereotypeApplicationTest.class, MergeDiffInvolvingRefineDiffTest.class, TestNonRegPseudoConflict_484576.class, RemoveStereotypeApplicationPseudoConflictTest.class, - MultiplicityElementChangesTest.class, InstanceSpecificationClassifiersMergeTest.class, }) + MultiplicityElementChangesTest.class, InstanceSpecificationClassifiersMergeTest.class, + AddMessageSubDiffTest.class, }) public class AllTests { /** diff --git a/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/merge/OpaqueElementBodyChangeMerger.java b/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/merge/OpaqueElementBodyChangeMerger.java index e806fd60b..a74fc0f96 100644 --- a/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/merge/OpaqueElementBodyChangeMerger.java +++ b/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/merge/OpaqueElementBodyChangeMerger.java @@ -7,9 +7,11 @@ * * Contributors: * Philip Langer - initial API and implementation + * Martin Fleck - bug 507177: consider refinement behavior *******************************************************************************/ package org.eclipse.emf.compare.uml2.internal.merge; +import static org.eclipse.emf.compare.DifferenceState.MERGED; import static org.eclipse.emf.compare.uml2.internal.postprocessor.util.UMLCompareUtil.getOpaqueElementLanguages; import static org.eclipse.emf.compare.uml2.internal.postprocessor.util.UMLCompareUtil.isChangeOfOpaqueElementBodyAttribute; import static org.eclipse.emf.compare.uml2.internal.postprocessor.util.UMLCompareUtil.isChangeOfOpaqueElementLanguageAttribute; @@ -113,12 +115,37 @@ public class OpaqueElementBodyChangeMerger extends AttributeChangeMerger { return Optional.absent(); } + /** + * Returns true if the complete body change has been merged, i.e., the change and all its refinements. + * + * @param bodyChange + * The {@link OpaqueElementBodyChange} to check. + * @return true if the complete body change is merged, false otherwise. + */ + private boolean isFullyMerged(OpaqueElementBodyChange bodyChange) { + if (bodyChange.getState() != MERGED) { + return false; + } + for (Diff refiningDiff : bodyChange.getRefinedBy()) { + if (refiningDiff.getState() != MERGED) { + return false; + } + } + return true; + } + @Override protected void accept(Diff diff, boolean rightToLeft) { final Optional<OpaqueElementBodyChange> possibleBodyChange = getOpaqueElementBodyChange(diff); if (possibleBodyChange.isPresent()) { final OpaqueElementBodyChange bodyChange = getOpaqueElementBodyChange(diff).get(); + // ensure that we do not merge an already MERGED OpaqueElementChange, e.g., when both language and + // body try to merge it + if (isFullyMerged(bodyChange)) { + return; + } + if (LOGGER.isDebugEnabled()) { int refinedElementCount = bodyChange.getRefinedBy().size(); LOGGER.debug("accept(Diff, boolean) - " + refinedElementCount //$NON-NLS-1$ @@ -142,6 +169,9 @@ public class OpaqueElementBodyChangeMerger extends AttributeChangeMerger { break; } + + // we set the whole refinement diff to merged + setFullyMerged(bodyChange); } } @@ -151,6 +181,12 @@ public class OpaqueElementBodyChangeMerger extends AttributeChangeMerger { if (possibleBodyChange.isPresent()) { final OpaqueElementBodyChange bodyChange = possibleBodyChange.get(); + // ensure that we do not merge an already MERGED OpaqueElementChange, e.g., when both language and + // body try to merge it + if (isFullyMerged(bodyChange)) { + return; + } + if (LOGGER.isDebugEnabled()) { int refinedElementCount = bodyChange.getRefinedBy().size(); LOGGER.debug("Reject(Diff, boolean)" + refinedElementCount //$NON-NLS-1$ @@ -173,6 +209,9 @@ public class OpaqueElementBodyChangeMerger extends AttributeChangeMerger { default: break; } + + // we set the whole refinement diff to merged + setFullyMerged(bodyChange); } } @@ -186,7 +225,6 @@ public class OpaqueElementBodyChangeMerger extends AttributeChangeMerger { * The direction of merging. */ private void acceptRefiningDiffs(OpaqueElementBodyChange bodyChange, boolean rightToLeft) { - bodyChange.setState(DifferenceState.MERGED); final List<Diff> sortedRefiningDiffs = sortByMergePriority(bodyChange.getRefinedBy()); for (Diff refiningDiff : sortedRefiningDiffs) { super.accept(refiningDiff, rightToLeft); @@ -203,7 +241,6 @@ public class OpaqueElementBodyChangeMerger extends AttributeChangeMerger { * The direction of merging. */ private void rejectRefiningDiffs(OpaqueElementBodyChange bodyChange, boolean rightToLeft) { - bodyChange.setState(DifferenceState.MERGED); final List<Diff> sortedRefiningDiffs = sortByMergePriority(bodyChange.getRefinedBy()); for (Diff refiningDiff : sortedRefiningDiffs) { super.reject(refiningDiff, rightToLeft); @@ -260,9 +297,6 @@ public class OpaqueElementBodyChangeMerger extends AttributeChangeMerger { final String targetValue = getTargetBodyValue(bodyChange, rightToLeft); setBody(targetContainer, targetValue, bodyChange.getLanguage()); - - // we merge the body change as a whole, so set all refining to merged too - setRefiningDiffsMerged(bodyChange); } /** @@ -453,9 +487,6 @@ public class OpaqueElementBodyChangeMerger extends AttributeChangeMerger { final int targetIndex = DiffUtil.findInsertionIndex(comparison, languageAttributeMove, rightToLeft); doMove(container, sourceIndex, targetIndex); - - // we merged the body change as a whole, so set all refining to merged too - setRefiningDiffsMerged(bodyChange); } /** @@ -553,12 +584,14 @@ public class OpaqueElementBodyChangeMerger extends AttributeChangeMerger { } /** - * Sets the {@link DifferenceState state} of all refining differences to merged. + * Sets the {@link DifferenceState state} of all refinement differences, i.e., the body change and its + * refining diffs, to merged. * * @param bodyChange - * The {@link OpaqueElementBodyChange} to set its refining differences to merged. + * The {@link OpaqueElementBodyChange} to set to merged. */ - private void setRefiningDiffsMerged(OpaqueElementBodyChange bodyChange) { + private void setFullyMerged(OpaqueElementBodyChange bodyChange) { + bodyChange.setState(DifferenceState.MERGED); for (Diff refiningDiff : bodyChange.getRefinedBy()) { refiningDiff.setState(DifferenceState.MERGED); } diff --git a/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/AbstractUMLChangeFactory.java b/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/AbstractUMLChangeFactory.java index 5dbd0508d..37851a165 100644 --- a/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/AbstractUMLChangeFactory.java +++ b/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/AbstractUMLChangeFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2015 Obeo. + * Copyright (c) 2013, 2016 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 @@ -7,6 +7,7 @@ * * Contributors: * Obeo - initial API and implementation + * Martin Fleck - bug 507177 *******************************************************************************/ package org.eclipse.emf.compare.uml2.internal.postprocessor; @@ -14,12 +15,14 @@ import static com.google.common.base.Predicates.instanceOf; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; -import com.google.common.collect.HashMultimap; import com.google.common.collect.Iterables; import com.google.common.collect.Iterators; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.SetMultimap; -import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -168,7 +171,7 @@ public abstract class AbstractUMLChangeFactory extends AbstractChangeFactory { private final Comparison fComparison; /** The specified settings. */ - private final HashMultimap<Object, RefiningCandidate> fRefiningCandidates; + private final SetMultimap<Object, RefiningCandidate> fRefiningCandidates; /** * Constructor. @@ -179,7 +182,7 @@ public abstract class AbstractUMLChangeFactory extends AbstractChangeFactory { * The specified settings. */ DifferencesOnRefiningCandidates(Comparison comparison, - HashMultimap<Object, RefiningCandidate> refiningCandidates) { + SetMultimap<Object, RefiningCandidate> refiningCandidates) { fComparison = comparison; fRefiningCandidates = refiningCandidates; } @@ -268,7 +271,7 @@ public abstract class AbstractUMLChangeFactory extends AbstractChangeFactory { */ @Override public void setRefiningChanges(Diff extension, DifferenceKind extensionKind, Diff refiningDiff) { - HashMultimap<Object, RefiningCandidate> refiningCandidates = HashMultimap.create(); + SetMultimap<Object, RefiningCandidate> refiningCandidates = LinkedHashMultimap.create(); Comparison comparison = ComparisonUtil.getComparison(refiningDiff); // From each discriminant business object, ... @@ -405,7 +408,7 @@ public abstract class AbstractUMLChangeFactory extends AbstractChangeFactory { */ protected static Set<EObject> defaultCaseForDiscriminantsGetter(Switch<Set<EObject>> discriminantsGetter, EObject object) { - Set<EObject> result = new HashSet<EObject>(); + Set<EObject> result = new LinkedHashSet<EObject>(); EObject parent = object.eContainer(); if (parent != null) { result.addAll(discriminantsGetter.doSwitch(parent)); @@ -436,7 +439,7 @@ public abstract class AbstractUMLChangeFactory extends AbstractChangeFactory { * differences. This map must not be null. */ private void defineRefiningCandidates(EObject discriminant, - HashMultimap<Object, RefiningCandidate> refiningCandidates) { + Multimap<Object, RefiningCandidate> refiningCandidates) { // The discriminant itself is a candidate, only on an incoming containment reference. refiningCandidates.put(discriminant, new RefiningCandidate()); // Delegation to a recursive method to find the other candidates. @@ -456,7 +459,7 @@ public abstract class AbstractUMLChangeFactory extends AbstractChangeFactory { * differences. This map must not be null. */ private void defineRefiningCandidatesFrom(EObject discriminant, - HashMultimap<Object, RefiningCandidate> refiningCandidates) { + Multimap<Object, RefiningCandidate> refiningCandidates) { Iterator<EStructuralFeature> outgoingFeatures = discriminant.eClass().getEAllStructuralFeatures() .iterator(); while (outgoingFeatures.hasNext()) { diff --git a/plugins/org.eclipse.emf.compare/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.compare/META-INF/MANIFEST.MF index 650312c11..021854e5e 100644 --- a/plugins/org.eclipse.emf.compare/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.emf.compare/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.emf.compare -Bundle-Version: 3.4.0.qualifier +Bundle-Version: 3.5.0.qualifier Bundle-ClassPath: . Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -42,5 +42,6 @@ Bundle-ActivationPolicy: lazy Import-Package: com.google.common.base;version="[11.0.0,16.0.0)", com.google.common.cache;version="[11.0.0,16.0.0)", com.google.common.collect;version="[11.0.0,16.0.0)", + com.google.common.eventbus;version="15.0.0", com.google.common.util.concurrent;version="[11.0.0,16.0.0)", org.apache.log4j;version="[1.2.15,2.0.0)" diff --git a/plugins/org.eclipse.emf.compare/model/compare.ecore b/plugins/org.eclipse.emf.compare/model/compare.ecore index 346f48791..60c27ffe4 100644 --- a/plugins/org.eclipse.emf.compare/model/compare.ecore +++ b/plugins/org.eclipse.emf.compare/model/compare.ecore @@ -395,7 +395,7 @@ </eClassifiers> <eClassifiers xsi:type="ecore:EEnum" name="DifferenceState"> <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel"> - <details key="documentation" value="This will be used to represent the state of a detected diff.
<ul>
	<li>UNRESOLVED if the Diff is still in its initial state and the two sides differ,</li>
	<li>MERGED if the Diff has already been merged by the user,</li>
	<li>DISCARDED if the user chose to ignore this Diff.</li>
</ul>"/> + <details key="documentation" value="This will be used to represent the state of a detected diff.
<ul>
	<li>UNRESOLVED if the Diff is still in its initial state and the two sides differ,</li>
	<li>MERGED if the Diff has already been merged by the user,</li>
	<li>DISCARDED if the user chose to ignore this Diff,</li>
	<li>MERGING if the Diff is in the process of being merged.</li>
</ul>"/> </eAnnotations> <eLiterals name="UNRESOLVED" literal="UNRESOLVED"> <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel"> @@ -412,6 +412,11 @@ <details key="documentation" value="Indicates that the user chose to ignore this Diff."/> </eAnnotations> </eLiterals> + <eLiterals name="MERGING" value="3" literal="MERGING"> + <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel"> + <details key="documentation" value="Indicates that the Diff is in the process of being merged."/> + </eAnnotations> + </eLiterals> </eClassifiers> <eClassifiers xsi:type="ecore:EEnum" name="ConflictKind"> <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel"> diff --git a/plugins/org.eclipse.emf.compare/pom.xml b/plugins/org.eclipse.emf.compare/pom.xml index 48cd7687e..bd77cb96a 100644 --- a/plugins/org.eclipse.emf.compare/pom.xml +++ b/plugins/org.eclipse.emf.compare/pom.xml @@ -10,6 +10,6 @@ </parent> <groupId>org.eclipse.emf.compare</groupId> <artifactId>org.eclipse.emf.compare</artifactId> - <version>3.4.0-SNAPSHOT</version> + <version>3.5.0-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> </project> diff --git a/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/DifferenceState.java b/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/DifferenceState.java index 8d44b08d3..fd51f65c5 100644 --- a/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/DifferenceState.java +++ b/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/DifferenceState.java @@ -17,27 +17,25 @@ import java.util.List; import org.eclipse.emf.common.util.Enumerator; /** - * <!-- begin-user-doc --> - * A representation of the literals of the enumeration '<em><b>Difference State</b></em>', - * and utility methods for working with them. - * <!-- end-user-doc --> - * <!-- begin-model-doc --> + * <!-- begin-user-doc --> A representation of the literals of the enumeration '<em><b>Difference + * State</b></em>', and utility methods for working with them. <!-- end-user-doc --> <!-- begin-model-doc --> * This will be used to represent the state of a detected diff. * <ul> - * <li>UNRESOLVED if the Diff is still in its initial state and the two sides differ,</li> - * <li>MERGED if the Diff has already been merged by the user,</li> - * <li>DISCARDED if the user chose to ignore this Diff.</li> + * <li>UNRESOLVED if the Diff is still in its initial state and the two sides differ,</li> + * <li>MERGED if the Diff has already been merged by the user,</li> + * <li>DISCARDED if the user chose to ignore this Diff,</li> + * <li>MERGING if the Diff is in the process of being merged.</li> * </ul> * <!-- end-model-doc --> + * * @see org.eclipse.emf.compare.ComparePackage#getDifferenceState() * @model * @generated */ public enum DifferenceState implements Enumerator { /** - * The '<em><b>UNRESOLVED</b></em>' literal object. - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * The '<em><b>UNRESOLVED</b></em>' literal object. <!-- begin-user-doc --> <!-- end-user-doc --> + * * @see #UNRESOLVED_VALUE * @generated * @ordered @@ -45,9 +43,8 @@ public enum DifferenceState implements Enumerator { UNRESOLVED(0, "UNRESOLVED", "UNRESOLVED"), //$NON-NLS-1$ //$NON-NLS-2$ /** - * The '<em><b>MERGED</b></em>' literal object. - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * The '<em><b>MERGED</b></em>' literal object. <!-- begin-user-doc --> <!-- end-user-doc --> + * * @see #MERGED_VALUE * @generated * @ordered @@ -55,29 +52,35 @@ public enum DifferenceState implements Enumerator { MERGED(1, "MERGED", "MERGED"), //$NON-NLS-1$ //$NON-NLS-2$ /** - * The '<em><b>DISCARDED</b></em>' literal object. - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * The '<em><b>DISCARDED</b></em>' literal object. <!-- begin-user-doc --> <!-- end-user-doc --> + * * @see #DISCARDED_VALUE * @generated * @ordered */ - DISCARDED(2, "DISCARDED", "DISCARDED"); //$NON-NLS-1$ //$NON-NLS-2$ + DISCARDED(2, "DISCARDED", "DISCARDED"), //$NON-NLS-1$ //$NON-NLS-2$ /** - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * The '<em><b>MERGING</b></em>' literal object. <!-- begin-user-doc --> <!-- end-user-doc --> + * + * @see #MERGING_VALUE + * @generated + * @ordered + * @since 3.5 + */ + MERGING(3, "MERGING", "MERGING"); //$NON-NLS-1$ //$NON-NLS-2$ + + /** + * <!-- begin-user-doc --> <!-- end-user-doc --> + * * @generated */ public static final String copyright = "Copyright (c) 2012 Obeo.\r\nAll rights reserved. This program and the accompanying materials\r\nare made available under the terms of the Eclipse Public License v1.0\r\nwhich accompanies this distribution, and is available at\r\nhttp://www.eclipse.org/legal/epl-v10.html\r\n\r\nContributors:\r\n Obeo - initial API and implementation"; //$NON-NLS-1$ /** - * The '<em><b>UNRESOLVED</b></em>' literal value. - * <!-- begin-user-doc --> - * <!-- end-user-doc --> - * <!-- begin-model-doc --> - * Indicates that the Diff is still in its initial state. - * <!-- end-model-doc --> + * The '<em><b>UNRESOLVED</b></em>' literal value. <!-- begin-user-doc --> <!-- end-user-doc --> <!-- + * begin-model-doc --> Indicates that the Diff is still in its initial state. <!-- end-model-doc --> + * * @see #UNRESOLVED * @model * @generated @@ -86,12 +89,9 @@ public enum DifferenceState implements Enumerator { public static final int UNRESOLVED_VALUE = 0; /** - * The '<em><b>MERGED</b></em>' literal value. - * <!-- begin-user-doc --> - * <!-- end-user-doc --> - * <!-- begin-model-doc --> - * Indicates that the Diff has already been merged by the user. - * <!-- end-model-doc --> + * The '<em><b>MERGED</b></em>' literal value. <!-- begin-user-doc --> <!-- end-user-doc --> <!-- + * begin-model-doc --> Indicates that the Diff has already been merged by the user. <!-- end-model-doc --> + * * @see #MERGED * @model * @generated @@ -100,12 +100,9 @@ public enum DifferenceState implements Enumerator { public static final int MERGED_VALUE = 1; /** - * The '<em><b>DISCARDED</b></em>' literal value. - * <!-- begin-user-doc --> - * <!-- end-user-doc --> - * <!-- begin-model-doc --> - * Indicates that the user chose to ignore this Diff. - * <!-- end-model-doc --> + * The '<em><b>DISCARDED</b></em>' literal value. <!-- begin-user-doc --> <!-- end-user-doc --> <!-- + * begin-model-doc --> Indicates that the user chose to ignore this Diff. <!-- end-model-doc --> + * * @see #DISCARDED * @model * @generated @@ -114,27 +111,39 @@ public enum DifferenceState implements Enumerator { public static final int DISCARDED_VALUE = 2; /** - * An array of all the '<em><b>Difference State</b></em>' enumerators. - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * The '<em><b>MERGING</b></em>' literal value. <!-- begin-user-doc --> <!-- end-user-doc --> <!-- + * begin-model-doc --> Indicates that the Diff is in the process of being merged. <!-- end-model-doc --> + * + * @see #MERGING + * @model + * @generated + * @ordered + * @since 3.4 + */ + public static final int MERGING_VALUE = 3; + + /** + * An array of all the '<em><b>Difference State</b></em>' enumerators. <!-- begin-user-doc --> <!-- + * end-user-doc --> + * * @generated */ private static final DifferenceState[] VALUES_ARRAY = new DifferenceState[] {UNRESOLVED, MERGED, - DISCARDED, }; + DISCARDED, MERGING, }; /** - * A public read-only list of all the '<em><b>Difference State</b></em>' enumerators. - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * A public read-only list of all the '<em><b>Difference State</b></em>' enumerators. <!-- begin-user-doc + * --> <!-- end-user-doc --> + * * @generated */ - public static final List<DifferenceState> VALUES = Collections.unmodifiableList(Arrays - .asList(VALUES_ARRAY)); + public static final List<DifferenceState> VALUES = Collections + .unmodifiableList(Arrays.asList(VALUES_ARRAY)); /** - * Returns the '<em><b>Difference State</b></em>' literal with the specified literal value. - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * Returns the '<em><b>Difference State</b></em>' literal with the specified literal value. <!-- + * begin-user-doc --> <!-- end-user-doc --> + * * @generated */ public static DifferenceState get(String literal) { @@ -148,9 +157,9 @@ public enum DifferenceState implements Enumerator { } /** - * Returns the '<em><b>Difference State</b></em>' literal with the specified name. - * <!-- begin-user-doc --> + * Returns the '<em><b>Difference State</b></em>' literal with the specified name. <!-- begin-user-doc --> * <!-- end-user-doc --> + * * @generated */ public static DifferenceState getByName(String name) { @@ -164,9 +173,9 @@ public enum DifferenceState implements Enumerator { } /** - * Returns the '<em><b>Difference State</b></em>' literal with the specified integer value. - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * Returns the '<em><b>Difference State</b></em>' literal with the specified integer value. <!-- + * begin-user-doc --> <!-- end-user-doc --> + * * @generated */ public static DifferenceState get(int value) { @@ -177,35 +186,36 @@ public enum DifferenceState implements Enumerator { return MERGED; case DISCARDED_VALUE: return DISCARDED; + case MERGING_VALUE: + return MERGING; } return null; } /** - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * <!-- begin-user-doc --> <!-- end-user-doc --> + * * @generated */ private final int value; /** - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * <!-- begin-user-doc --> <!-- end-user-doc --> + * * @generated */ private final String name; /** - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * <!-- begin-user-doc --> <!-- end-user-doc --> + * * @generated */ private final String literal; /** - * Only this class can construct instances. - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * Only this class can construct instances. <!-- begin-user-doc --> <!-- end-user-doc --> + * * @generated */ private DifferenceState(int value, String name, String literal) { @@ -215,8 +225,8 @@ public enum DifferenceState implements Enumerator { } /** - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * <!-- begin-user-doc --> <!-- end-user-doc --> + * * @generated */ public int getValue() { @@ -224,8 +234,8 @@ public enum DifferenceState implements Enumerator { } /** - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * <!-- begin-user-doc --> <!-- end-user-doc --> + * * @generated */ public String getName() { @@ -233,8 +243,8 @@ public enum DifferenceState implements Enumerator { } /** - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * <!-- begin-user-doc --> <!-- end-user-doc --> + * * @generated */ public String getLiteral() { @@ -242,9 +252,9 @@ public enum DifferenceState implements Enumerator { } /** - * Returns the literal value of the enumerator, which is its string representation. - * <!-- begin-user-doc --> - * <!-- end-user-doc --> + * Returns the literal value of the enumerator, which is its string representation. <!-- begin-user-doc + * --> <!-- end-user-doc --> + * * @generated */ @Override @@ -252,4 +262,4 @@ public enum DifferenceState implements Enumerator { return literal; } -} //DifferenceState +} // DifferenceState diff --git a/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/impl/ComparePackageImpl.java b/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/impl/ComparePackageImpl.java index 7d1521d91..d7b4117fa 100644 --- a/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/impl/ComparePackageImpl.java +++ b/plugins/org.eclipse.emf.compare/src-gen/org/eclipse/emf/compare/impl/ComparePackageImpl.java @@ -1160,6 +1160,7 @@ public class ComparePackageImpl extends EPackageImpl implements ComparePackage { addEEnumLiteral(differenceStateEEnum, DifferenceState.UNRESOLVED); addEEnumLiteral(differenceStateEEnum, DifferenceState.MERGED); addEEnumLiteral(differenceStateEEnum, DifferenceState.DISCARDED); + addEEnumLiteral(differenceStateEEnum, DifferenceState.MERGING); initEEnum(conflictKindEEnum, ConflictKind.class, "ConflictKind"); //$NON-NLS-1$ addEEnumLiteral(conflictKindEEnum, ConflictKind.REAL); diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/merge/MergeDependenciesUtil.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/merge/MergeDependenciesUtil.java index d7078c69b..ed5285634 100644 --- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/merge/MergeDependenciesUtil.java +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/merge/MergeDependenciesUtil.java @@ -8,33 +8,24 @@ * Contributors: * Obeo - initial API and implementation * Philip Langer - bug 462884 + * Martin Fleck - bug 507177 *******************************************************************************/ package org.eclipse.emf.compare.internal.merge; +import static com.google.common.base.Predicates.and; import static com.google.common.base.Predicates.not; -import static com.google.common.collect.Iterables.addAll; import static org.eclipse.emf.compare.ConflictKind.PSEUDO; -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.sameSideAs; -import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import com.google.common.collect.Iterables; import com.google.common.collect.Sets; +import com.google.common.collect.Sets.SetView; -import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; -import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.Diff; -import org.eclipse.emf.compare.DifferenceSource; -import org.eclipse.emf.compare.graph.IGraph; -import org.eclipse.emf.compare.internal.utils.ComparisonUtil; -import org.eclipse.emf.compare.internal.utils.Graph; -import org.eclipse.emf.compare.merge.AbstractMerger; -import org.eclipse.emf.compare.merge.IMergeOptionAware; import org.eclipse.emf.compare.merge.IMerger; import org.eclipse.emf.compare.merge.IMerger2; @@ -50,78 +41,6 @@ public final class MergeDependenciesUtil { } /** - * This will map all the differences from the given comparison in a dependency graph, enabling EMF Compare - * to differentiate what can be safely merged from what cannot. - * - * @param comparison - * The comparison which differences are to be mapped into a dependency graph. - * @param mergerRegistry - * The {@link IMerger.Registry merger registry} currently in use. - * @param mergeRightToLeft - * The direction in which we're preparing a merge. - * @param mergeMode - * The merge mode. If MergeMode is null, then no differences will be filtered. - * @return The dependency graph of this comparison's differences. - * @see #mapDifferences(Collection, org.eclipse.emf.compare.merge.IMerger.Registry, boolean, MergeMode) - */ - public static IGraph<Diff> mapDifferences(Comparison comparison, IMerger.Registry mergerRegistry, - boolean mergeRightToLeft, MergeMode mergeMode) { - return mapDifferences(comparison.getDifferences(), mergerRegistry, mergeRightToLeft, mergeMode); - } - - /** - * This will map the given differences in a dependency graph, enabling EMF Compare to differentiate what - * can be safely merged from what cannot. - * <p> - * Typically, all differences that are not in a real conflict with another and that do not depend, - * directly or indirectly, on a conflicting difference can be pre-merged without corrupting the models. - * For example, if adding a reference "ref1" to an added class "C1" depends on the addition of a package - * "P1" (i.e. three additions in a row), but "C1" has also been added in another place in the other model - * (a conflict between two "same" elements added into different containers), then we can safely pre-merge - * the addition of P1, but not the addition of its contained class C1, nor the addition of ref1. - * </p> - * - * @param differences - * The differences to be mapped into a dependency graph. - * @param mergerRegistry - * The {@link IMerger.Registry merger registry} currently in use. - * @param mergeRightToLeft - * The direction in which we're preparing a merge. - * @param mergeMode - * The merge mode. If MergeMode is null, then no differences will be filtered. - * @return The dependency graph of this comparison's differences. - */ - public static IGraph<Diff> mapDifferences(Collection<Diff> differences, IMerger.Registry mergerRegistry, - boolean mergeRightToLeft, MergeMode mergeMode) { - IGraph<Diff> differencesGraph = new Graph<Diff>(); - final Predicate<? super Diff> filter; - if (mergeMode == MergeMode.RIGHT_TO_LEFT) { - filter = fromSide(DifferenceSource.RIGHT); - } else if (mergeMode == MergeMode.LEFT_TO_RIGHT) { - filter = fromSide(DifferenceSource.LEFT); - } else { - filter = Predicates.alwaysTrue(); - } - for (Diff diff : Iterables.filter(differences, filter)) { - final IMerger merger = mergerRegistry.getHighestRankingMerger(diff); - final Set<Diff> directParents; - if (merger instanceof IMerger2) { - directParents = ((IMerger2)merger).getDirectMergeDependencies(diff, mergeRightToLeft); - } else { - directParents = Collections.emptySet(); - } - if (directParents.isEmpty()) { - differencesGraph.add(diff); - } else { - for (Diff parent : directParents) { - differencesGraph.addChildren(parent, Collections.singleton(diff)); - } - } - } - return differencesGraph; - } - - /** * Retrieves the set of all diffs related to the given <code>diff</code> when merging in the given * direction. * <p> @@ -132,25 +51,28 @@ public final class MergeDependenciesUtil { * <p> * Note that <code>diff</code> will be included in the returned set. * </p> + * <p> + * Also note that the resulting merges will contain the resulting rejections (diffs from the other side + * that will be rejected) + * </p> * * @param diff * The difference for which we seek all related ones. * @param mergerRegistry * The {@link IMerger.Registry merger registry} currently in use. - * @param mergeRightToLeft + * @param rightToLeft * The direction in which we're considering a merge. * @return The set of all diffs related to the given <code>diff</code> when merging in the given * direction. */ public static Set<Diff> getAllResultingMerges(Diff diff, IMerger.Registry mergerRegistry, - boolean mergeRightToLeft) { + boolean rightToLeft) { final Set<Diff> resultingMerges = new LinkedHashSet<Diff>(); resultingMerges.add(diff); - Set<Diff> relations = internalGetResultingMerges(diff, mergerRegistry, mergeRightToLeft, - diff.getSource()); + Set<Diff> relations = internalGetResultingMerges(diff, mergerRegistry, rightToLeft); // We don't want to take in account pseudo conflicts since there is nothing to do with them - // and there dependencies may cause incorrect merge dependencies computation. + // and their dependencies may cause incorrect merge dependencies computation. Set<Diff> difference = Sets.filter(Sets.difference(relations, resultingMerges), not(hasConflict(PSEUDO))); while (!difference.isEmpty()) { @@ -159,7 +81,7 @@ public final class MergeDependenciesUtil { relations = new LinkedHashSet<Diff>(); for (Diff newRelation : newRelations) { Set<Diff> internalResultingMerges = internalGetResultingMerges(newRelation, mergerRegistry, - mergeRightToLeft, diff.getSource()); + rightToLeft); // We don't want to take in account pseudo conflicts since there is nothing to do with them // and there dependencies may cause incorrect merge dependencies computation. relations.addAll(Sets.filter(internalResultingMerges, not(hasConflict(PSEUDO)))); @@ -184,45 +106,24 @@ public final class MergeDependenciesUtil { * The difference for which we seek all directly related others. * @param mergerRegistry * The {@link IMerger.Registry merger registry} currently in use. - * @param mergeRightToLeft + * @param rightToLeft * The direction in which we're considering a merge. - * @param originalSource - * The original side of the diff the dependencies of which we are computing * @return The set of all differences <b>directly</b> related to the given one. */ private static Set<Diff> internalGetResultingMerges(Diff diff, IMerger.Registry mergerRegistry, - boolean mergeRightToLeft, DifferenceSource originalSource) { + boolean rightToLeft) { final IMerger merger = mergerRegistry.getHighestRankingMerger(diff); - // If a (pseudo-)conflict makes use merge diffs from the other side, - // we must then look for the consequences of these diffs - // as if they had been merged the other way around. - final boolean direction; - if (diff.getSource() == originalSource) { - direction = mergeRightToLeft; - } else { - direction = !mergeRightToLeft; - } final Set<Diff> directParents; final Set<Diff> directImplications; if (merger instanceof IMerger2) { - directParents = ((IMerger2)merger).getDirectMergeDependencies(diff, direction); - directImplications = ((IMerger2)merger).getDirectResultingMerges(diff, direction); + directParents = ((IMerger2)merger).getDirectMergeDependencies(diff, rightToLeft); + directImplications = ((IMerger2)merger).getDirectResultingMerges(diff, rightToLeft); } else { directParents = Collections.emptySet(); directImplications = Collections.emptySet(); } - // FIXME [PERF] Useless copy - final LinkedHashSet<Diff> directRelated = Sets - .newLinkedHashSet(Sets.union(directParents, directImplications)); - - if (merger instanceof IMergeOptionAware) { - Object subDiffs = ((IMergeOptionAware)merger).getMergeOptions() - .get(AbstractMerger.SUB_DIFF_AWARE_OPTION); - if (subDiffs == Boolean.TRUE) { - addAll(directRelated, ComparisonUtil.getSubDiffs(!direction).apply(diff)); - } - } + final SetView<Diff> directRelated = Sets.union(directParents, directImplications); return directRelated; } @@ -245,13 +146,15 @@ public final class MergeDependenciesUtil { final Set<Diff> resultingRejections = new LinkedHashSet<Diff>(); final Set<Diff> allResultingMerges = getAllResultingMerges(diff, mergerRegistry, mergeRightToLeft); - for (Diff resulting : allResultingMerges) { - Set<Diff> rejections = internalGetResultingRejections(resulting, mergerRegistry, mergeRightToLeft, - diff.getSource()); + resultingRejections.addAll( + Sets.filter(allResultingMerges, and(not(hasConflict(PSEUDO)), not(sameSideAs(diff))))); + // Only search rejections caused by diffs on the same side + for (Diff resulting : Sets.filter(allResultingMerges, sameSideAs(diff))) { + Set<Diff> rejections = internalGetResultingRejections(resulting, mergerRegistry, + mergeRightToLeft); // We don't want to take in account pseudo conflicts since there is nothing to do with them - // and there dependencies may cause incorrect merge dependencies computation. - Set<Diff> difference = Sets.filter(Sets.difference(rejections, resultingRejections), - not(hasConflict(PSEUDO))); + // and their dependencies may cause incorrect merge dependencies computation. + Set<Diff> difference = Sets.filter(rejections, not(hasConflict(PSEUDO))); while (!difference.isEmpty()) { final Set<Diff> newRejections = new LinkedHashSet<Diff>(difference); resultingRejections.addAll(newRejections); @@ -262,11 +165,14 @@ public final class MergeDependenciesUtil { Set<Diff> directMergeDependencies = ((IMerger2)merger) .getDirectMergeDependencies(rejected, mergeRightToLeft); // We don't want to take in account pseudo conflicts since there is nothing to do with - // them and there dependencies may cause incorrect merge dependencies computation. - rejections.addAll(Sets.filter(directMergeDependencies, not(hasConflict(PSEUDO)))); + // them and their dependencies may cause incorrect merge dependencies computation. + // We also don't want to consider diffs on the same side for rejections + rejections.addAll(Sets.filter(directMergeDependencies, + and(not(hasConflict(PSEUDO)), not(sameSideAs(diff))))); Set<Diff> directResultingMerges = ((IMerger2)merger) .getDirectResultingMerges(rejected, mergeRightToLeft); - rejections.addAll(Sets.filter(directResultingMerges, not(hasConflict(PSEUDO)))); + rejections.addAll(Sets.filter(directResultingMerges, + and(not(hasConflict(PSEUDO)), not(sameSideAs(diff))))); } } difference = Sets.difference(rejections, resultingRejections); @@ -283,24 +189,16 @@ public final class MergeDependenciesUtil { * The difference for which we seek all opposite ones. * @param mergerRegistry * The {@link IMerger.Registry merger registry} currently in use. - * @param mergeRightToLeft + * @param rightToLeft * The direction in which we're considering a merge. - * @param originalSource - * The original side of the diff the dependencies of which we are computing * @return The set of all directly related differences that will be rejected if <code>diff</code> is * merged in the given direction. */ private static Set<Diff> internalGetResultingRejections(Diff diff, IMerger.Registry mergerRegistry, - boolean mergeRightToLeft, DifferenceSource originalSource) { - final boolean direction; - if (diff.getSource() == originalSource) { - direction = mergeRightToLeft; - } else { - direction = !mergeRightToLeft; - } + boolean rightToLeft) { final IMerger merger = mergerRegistry.getHighestRankingMerger(diff); if (merger instanceof IMerger2) { - return ((IMerger2)merger).getDirectResultingRejections(diff, direction); + return ((IMerger2)merger).getDirectResultingRejections(diff, rightToLeft); } return Collections.emptySet(); } diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/DiffUtil.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/DiffUtil.java index 89f2e2501..8f174a209 100644 --- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/DiffUtil.java +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/DiffUtil.java @@ -70,7 +70,8 @@ public final class DiffUtil { } /** - * The set of all the diffs that refine the given diff or one of its refining diffs, recursively. + * The set of all the diffs (atomic or not) that refine the given diff or one of its refining diffs, + * recursively. * * @param diff * The diff for which all the refining diffs are seeked @@ -112,12 +113,13 @@ public final class DiffUtil { } /** - * The set of all the diffs that refine the given diff or one of its refining diffs, recursively. + * The set of all the atomic diffs that refine the given diff or one of its refining diffs, recursively. + * An atomic diff is a diff that is not refined by any diff. * * @param diff * The diff for which all the refining diffs are seeked - * @return A set of all the refining diffs (as opposed to getting only the 1st level of refining diffs - * that would be obtained by calling getRefinedBy() on diff. + * @return A set of all the atomic refining diffs (as opposed to getting only the 1st level of refining + * diffs that would be obtained by calling getRefinedBy() on diff. */ public static Set<Diff> getAllAtomicRefiningDiffs(Diff diff) { Set<Diff> result = new LinkedHashSet<Diff>(); diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/Graph.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/Graph.java index 6abebbd13..03076813c 100644 --- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/Graph.java +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/utils/Graph.java @@ -19,8 +19,6 @@ import com.google.common.base.Predicate; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Iterators; -import com.google.common.collect.Sets; -import com.google.common.collect.Sets.SetView; import java.util.Collection; import java.util.Collections; @@ -1007,7 +1005,8 @@ public class Graph<E> implements IGraph<E> { /** {@inheritDoc} */ public boolean hasNext() { - return next != null || currentIterator.hasNext() || !consumedNodes.containsAll(nextIterable); + // next is updated after a node is returned or pruned + return next != null; } /** {@inheritDoc} */ @@ -1046,6 +1045,10 @@ public class Graph<E> implements IGraph<E> { } } } + // update next according to newly pruned nodes, if necessary + if (consumedNodes.contains(next)) { + prepareNext(); + } } /** @@ -1057,17 +1060,43 @@ public class Graph<E> implements IGraph<E> { throw new UnsupportedOperationException(); } - /** This will prepare this iterator for a subsequent call to {@link #next()}. */ + /** + * This method prepares the {@link #next()} node by checking first the current iterator if there are + * any unconsumed nodes left and if not switching to the next iterator. If neither the current nor the + * next iterator have any unconsumed nodes, next will be set to null. + */ private void prepareNext() { - if (!currentIterator.hasNext()) { + // check if current iterator still has unconsumed nodes + boolean isConsumed = true; + while (isConsumed) { + next = currentNext(); + // check if node has already been consumed (or pruned) + isConsumed = next != null && consumedNodes.contains(next); + } + + if (next == null) { + // could not find unconsumed nodes in current iterator, try next iterator prepareNextIterator(); + + // next iterator is now currentIterator only containing unconsumed nodes, if there are any + next = currentNext(); } + } + + /** + * Returns the next node from the current iterator, if such a node exists. The children of the next + * node will be remembered for the next iterator. + * + * @return current next node + */ + private Node<E> currentNext() { + Node<E> currentNext = null; if (currentIterator.hasNext()) { - next = currentIterator.next(); - nextIterable.addAll(next.getChildren()); - } else { - next = null; + currentNext = currentIterator.next(); + // remember children for next iterator + nextIterable.addAll(currentNext.getChildren()); } + return currentNext; } /** @@ -1081,12 +1110,7 @@ public class Graph<E> implements IGraph<E> { difference.add(node); } } - currentIterator = Iterators.filter(difference.iterator(), new Predicate<Node<E>>() { - public boolean apply(Node<E> input) { - SetView<Node<E>> trueParents = Sets.difference(input.getParents(), input.getChildren()); - return consumedNodes.containsAll(trueParents); - } - }); + currentIterator = difference.iterator(); nextIterable.clear(); } } diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AbstractMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AbstractMerger.java index 520d2c30a..84af4ae84 100644 --- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AbstractMerger.java +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AbstractMerger.java @@ -9,19 +9,24 @@ * Obeo - initial API and implementation * Stefan Dirix - bugs 441172, 452147 and 454579 * Alexandra Buzila - Fixes for Bug 446252 + * Martin Fleck - bug 507177 *******************************************************************************/ package org.eclipse.emf.compare.merge; import static com.google.common.base.Predicates.in; +import static com.google.common.base.Predicates.not; import static com.google.common.base.Predicates.or; -import static com.google.common.collect.Iterables.addAll; import static com.google.common.collect.Iterables.any; -import static com.google.common.collect.Iterables.concat; -import static com.google.common.collect.Iterables.transform; -import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide; +import static org.eclipse.emf.compare.ConflictKind.PSEUDO; +import static org.eclipse.emf.compare.DifferenceSource.RIGHT; +import static org.eclipse.emf.compare.DifferenceState.MERGED; +import static org.eclipse.emf.compare.DifferenceState.MERGING; +import static org.eclipse.emf.compare.DifferenceState.UNRESOLVED; +import static org.eclipse.emf.compare.merge.IMergeCriterion.NONE; import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasConflict; import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasSameReferenceAs; import static org.eclipse.emf.compare.utils.EMFComparePredicates.isDiffOnEOppositeOf; +import static org.eclipse.emf.compare.utils.EMFComparePredicates.sameSideAs; import com.google.common.base.Optional; import com.google.common.base.Predicate; @@ -149,7 +154,7 @@ public abstract class AbstractMerger implements IMerger2, IMergeOptionAware, IMe * @since 3.4 */ public boolean apply(IMergeCriterion criterion) { - return criterion == null || criterion == AdditiveMergeCriterion.INSTANCE; + return criterion == null || criterion == NONE || criterion == AdditiveMergeCriterion.INSTANCE; } /** @@ -191,23 +196,14 @@ public abstract class AbstractMerger implements IMerger2, IMergeOptionAware, IMe */ public Set<Diff> getDirectMergeDependencies(Diff diff, boolean mergeRightToLeft) { long start = System.currentTimeMillis(); + final Set<Diff> dependencies = new LinkedHashSet<Diff>(); - if (mergeRightToLeft) { - if (DifferenceSource.LEFT == diff.getSource()) { - dependencies.addAll(diff.getImplies()); - dependencies.addAll(diff.getRequiredBy()); - } else { - dependencies.addAll(diff.getImpliedBy()); - dependencies.addAll(diff.getRequires()); - } + if (isAccepting(diff, mergeRightToLeft)) { + dependencies.addAll(diff.getRequires()); + dependencies.addAll(diff.getImpliedBy()); } else { - if (DifferenceSource.LEFT == diff.getSource()) { - dependencies.addAll(diff.getImpliedBy()); - dependencies.addAll(diff.getRequires()); - } else { - dependencies.addAll(diff.getImplies()); - dependencies.addAll(diff.getRequiredBy()); - } + dependencies.addAll(diff.getImplies()); + dependencies.addAll(diff.getRequiredBy()); } dependencies.addAll(diff.getRefinedBy()); if (diff.getEquivalence() != null) { @@ -235,58 +231,10 @@ public abstract class AbstractMerger implements IMerger2, IMergeOptionAware, IMe */ public Set<Diff> getDirectResultingMerges(Diff target, boolean mergeRightToLeft) { long start = System.currentTimeMillis(); - final Set<Diff> resulting = new LinkedHashSet<Diff>(); - if (mergeRightToLeft) { - if (DifferenceSource.LEFT == target.getSource()) { - resulting.addAll(target.getImpliedBy()); - } else { - resulting.addAll(target.getImplies()); - } - } else { - if (DifferenceSource.LEFT == target.getSource()) { - resulting.addAll(target.getImplies()); - } else { - resulting.addAll(target.getImpliedBy()); - } - } - if (target.getEquivalence() != null) { - resulting.addAll(target.getEquivalence().getDifferences()); - resulting.remove(target); - } - if (target.getConflict() != null && target.getConflict().getKind() == ConflictKind.PSEUDO) { - resulting.addAll(target.getConflict().getDifferences()); - resulting.remove(target); - } - // If a diff refines another, we have to check if the "macro" diff has to be merged with it. It is the - // case when the unresolved diffs that refine the "macro" diff are all contained by the set - // (target + resulting) (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=458961) - for (Diff refine : target.getRefines()) { - Set<Diff> tmp = Sets.newHashSet(resulting); - tmp.add(target); - Collection<Diff> unresolvedRefinedDiffs = Collections2.filter(refine.getRefinedBy(), - EMFComparePredicates.hasState(DifferenceState.UNRESOLVED)); - if (tmp.containsAll(unresolvedRefinedDiffs)) { - resulting.add(refine); - } - } - - // Bug 452147: - // Add interlocked differences to the resulting merges to avoid merging redundant differences with - // undefined consequences. - if (target instanceof ReferenceChange) { - final ReferenceChange refTarget = (ReferenceChange)target; - if (isOneToOneAndChange(refTarget)) { - resulting.addAll(findInterlockedOneToOneDiffs(refTarget, mergeRightToLeft)); - } - } - - if (isHandleSubDiffs()) { - final Set<Diff> resultingToMerge = Sets.newLinkedHashSet(resulting); - Iterable<Diff> subDiffs = concat( - transform(resultingToMerge, ComparisonUtil.getSubDiffs(!mergeRightToLeft))); - addAll(resulting, subDiffs); - } + final Set<Diff> resulting = new LinkedHashSet<Diff>(); + resulting.addAll(getImpliedMerges(target, mergeRightToLeft)); + resulting.addAll(getLogicallyResultingMerges(target, mergeRightToLeft)); if (LOGGER.isDebugEnabled()) { Long duration = new Long(System.currentTimeMillis() - start); @@ -399,18 +347,15 @@ public abstract class AbstractMerger implements IMerger2, IMergeOptionAware, IMe * * @since 3.2 */ - public Set<Diff> getDirectResultingRejections(Diff target, boolean mergeRightToLeft) { + public Set<Diff> getDirectResultingRejections(Diff target, boolean rightToLeft) { long start = System.currentTimeMillis(); final Set<Diff> directlyImpliedRejections = new LinkedHashSet<Diff>(); final Conflict conflict = target.getConflict(); if (conflict != null && conflict.getKind() == ConflictKind.REAL) { - if (mergeRightToLeft && target.getSource() == DifferenceSource.RIGHT) { + if (isAccepting(target, rightToLeft)) { Iterables.addAll(directlyImpliedRejections, - Iterables.filter(conflict.getDifferences(), fromSide(DifferenceSource.LEFT))); - } else if (!mergeRightToLeft && target.getSource() == DifferenceSource.LEFT) { - Iterables.addAll(directlyImpliedRejections, - Iterables.filter(conflict.getDifferences(), fromSide(DifferenceSource.RIGHT))); + Iterables.filter(conflict.getDifferences(), not(sameSideAs(target)))); } } @@ -496,6 +441,7 @@ public abstract class AbstractMerger implements IMerger2, IMergeOptionAware, IMe * The {@link Diff} to check. * @return {@code true} if the diff exists and has a conflict of kind {@link ConflictKind#REAL}, * {@code false} otherwise. + * @since 3.4 */ private boolean hasRealConflict(Diff diff) { return diff != null && diff.getConflict() != null @@ -718,211 +664,187 @@ public abstract class AbstractMerger implements IMerger2, IMergeOptionAware, IMe } /** - * {@inheritDoc} + * Returns a set of differences that should be logically merged with the given diff. As opposed to + * {@link #getDirectMergeDependencies(Diff, boolean) merge dependencies}, it is not structurally necessary + * to merge these diffs before the given diff. This may include the diff's {@link Diff#getImpliedBy() + * implications}, the diff's {@link Diff#getRefines() refinement} or any other diff that should be + * logically merged with the given diff. * - * @see org.eclipse.emf.compare.merge.IMerger#copyLeftToRight(org.eclipse.emf.compare.Diff, - * org.eclipse.emf.common.util.Monitor) - * @since 3.1 + * @param diff + * The difference we're considering merging. + * @param mergeRightToLeft + * The direction in which we're considering a merge. + * @return The Set of all differences that will be merged because we've merged <code>diff</code>. + * @since 3.5 */ - public void copyLeftToRight(Diff target, Monitor monitor) { - // Don't merge an already merged (or discarded) diff - if (target.getState() != DifferenceState.UNRESOLVED) { - return; - } + protected Set<Diff> getLogicallyResultingMerges(Diff diff, boolean mergeRightToLeft) { long start = System.currentTimeMillis(); - // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles. - target.setState(DifferenceState.MERGED); - - final Set<Diff> dependencies = getDirectMergeDependencies(target, false); - - // We'll redo some of the work from getDirectMergeDependencies here in order to ensure we haven't been - // merged by another diff (equivalence or implication). - // requiresMerging must be executed before actually merging the dependencies because - // findMasterEquivalence may return a different result after merging. - boolean requiresMerging = requiresMerging(target, false); + final Set<Diff> resulting = new LinkedHashSet<Diff>(); - for (Diff mergeMe : dependencies) { - mergeDiff(mergeMe, false, monitor); + // we need to add the implication side that actually needs merging + if (isAccepting(diff, mergeRightToLeft)) { + resulting.addAll(diff.getImpliedBy()); + } else { + resulting.addAll(diff.getImplies()); } - for (Diff transitiveMerge : getDirectResultingMerges(target, false)) { - transitiveMerge.setState(DifferenceState.MERGED); - } - - if (requiresMerging) { - if (target.getSource() == DifferenceSource.LEFT) { - accept(target, false); - } else { - reject(target, false); - } - } + // refinements should only be merged together + resulting.addAll(diff.getRefines()); + // any logically linked sub diffs should be merged as well if (isHandleSubDiffs()) { - Set<Diff> subDiffs = Sets.newLinkedHashSet(ComparisonUtil.getDirectSubDiffs(true).apply(target)); - for (Diff subDiff : subDiffs) { - mergeDiff(subDiff, false, monitor); - } + Set<Diff> subDiffs = Sets + .newLinkedHashSet(ComparisonUtil.getDirectSubDiffs(!mergeRightToLeft).apply(diff)); + resulting.addAll(subDiffs); } if (LOGGER.isDebugEnabled()) { - long duration = System.currentTimeMillis() - start; - LOGGER.debug("copyLeftToRight(Diff, Monitor) - diff " + target.hashCode() + " merged in " //$NON-NLS-1$ //$NON-NLS-2$ - + duration + "ms"); //$NON-NLS-1$ + Long duration = new Long(System.currentTimeMillis() - start); + String log = String.format( + "getLogicallyResultingMerges(Diff, boolean) - %d merges found in %d ms for diff %d", //$NON-NLS-1$ + new Integer(resulting.size()), duration, new Integer(diff.hashCode())); + LOGGER.debug(log); } + + return resulting; } /** - * {@inheritDoc} + * Returns all differences that are automatically set to the targets {@link Diff#getState() state} if the + * given target diff is merged. This may include the diff's {@link Diff#getImplies() implications}, the + * diff's {@link Diff#getEquivalence() equivalences} or any other diff that requires no merging by itself. * - * @see org.eclipse.emf.compare.merge.IMerger#copyRightToLeft(org.eclipse.emf.compare.Diff, - * org.eclipse.emf.common.util.Monitor) - * @since 3.1 + * @param target + * The difference we're considering merging. + * @param mergeRightToLeft + * The direction in which we're considering a merge. + * @return The Set of all differences that will be set to <code>MERGED</code> because we've merged + * <code>target</code>. + * @since 3.5 */ - public void copyRightToLeft(Diff target, Monitor monitor) { - // Don't merge an already merged (or discarded) diff - if (target.getState() != DifferenceState.UNRESOLVED) { - return; - } + protected Set<Diff> getImpliedMerges(Diff target, boolean mergeRightToLeft) { long start = System.currentTimeMillis(); + final Set<Diff> impliedMerges = new LinkedHashSet<Diff>(); - // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles. - target.setState(DifferenceState.MERGED); - - final Set<Diff> dependencies = getDirectMergeDependencies(target, true); - - // We'll redo some of the work from getDirectMergeDependencies here in order to ensure we haven't been - // merged by another diff (equivalence or implication). - // requiresMerging must be executed before actually merging the dependencies because - // findMasterEquivalence may return a different result after merging. - boolean requiresMerging = requiresMerging(target, true); + if (isAccepting(target, mergeRightToLeft)) { + impliedMerges.addAll(target.getImplies()); + } else { + impliedMerges.addAll(target.getImpliedBy()); + } - for (Diff mergeMe : dependencies) { - mergeDiff(mergeMe, true, monitor); + if (target.getEquivalence() != null) { + impliedMerges.addAll(target.getEquivalence().getDifferences()); + impliedMerges.remove(target); } - for (Diff transitiveMerge : getDirectResultingMerges(target, true)) { - transitiveMerge.setState(DifferenceState.MERGED); + if (target.getConflict() != null && target.getConflict().getKind() == PSEUDO) { + impliedMerges.addAll(target.getConflict().getDifferences()); + impliedMerges.remove(target); } - if (requiresMerging) { - if (target.getSource() == DifferenceSource.LEFT) { - reject(target, true); - } else { - accept(target, true); + // If a diff refines another, we have to check if the "macro" diff has to be merged with it. It is the + // case when the unresolved diffs that refine the "macro" diff are all contained by the set + // (target + resulting) (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=458961) + for (Diff refine : target.getRefines()) { + Set<Diff> tmp = Sets.newHashSet(impliedMerges); + tmp.add(target); + Collection<Diff> unresolvedRefinedDiffs = Collections2.filter(refine.getRefinedBy(), + EMFComparePredicates.hasState(UNRESOLVED)); + if (tmp.containsAll(unresolvedRefinedDiffs)) { + impliedMerges.add(refine); } } - if (isHandleSubDiffs()) { - Set<Diff> subDiffs = Sets.newLinkedHashSet(ComparisonUtil.getDirectSubDiffs(false).apply(target)); - for (Diff subDiff : subDiffs) { - mergeDiff(subDiff, true, monitor); + // Bug 452147: + // Add interlocked differences to the resulting merges to avoid merging redundant differences with + // undefined consequences. + if (target instanceof ReferenceChange) { + final ReferenceChange refTarget = (ReferenceChange)target; + if (isOneToOneAndChange(refTarget)) { + impliedMerges.addAll(findInterlockedOneToOneDiffs(refTarget, mergeRightToLeft)); } } if (LOGGER.isDebugEnabled()) { - long duration = System.currentTimeMillis() - start; - LOGGER.debug("copyLeftToRight(Diff, Monitor) - diff " + target.hashCode() + " merged in " //$NON-NLS-1$ //$NON-NLS-2$ - + duration + "ms"); //$NON-NLS-1$ + Long duration = new Long(System.currentTimeMillis() - start); + String log = String.format( + "getImpliedMerges(Diff, boolean) - %d implied merges found in %d ms for diff %d", //$NON-NLS-1$ + new Integer(impliedMerges.size()), duration, new Integer(target.hashCode())); + LOGGER.debug(log); } + return impliedMerges; } /** - * Checks whether the given diff still needs to be merged or if it has been merged because of an - * implication or 'master' equivalence. + * Executes a copy in the given merge direction. This method is a generalization of + * {@link #copyLeftToRight(Diff, Monitor)} and {@link #copyRightToLeft(Diff, Monitor)}. * * @param target - * The difference we are considering merging. - * @param mergeRightToLeft - * The direction in which we're considering a merge. - * @return <code>true</code> if the <code>target</code> diff hasn't been merged yet and requires handling - * of its own. + * The difference to handle. + * @param monitor + * Monitor. + * @param rightToLeft + * Merge direction. + * @since 3.5 */ - private boolean requiresMerging(Diff target, boolean mergeRightToLeft) { - boolean requiresMerging = true; - if (isImpliedMerge(target, mergeRightToLeft)) { - // first, if we are implied by something, then we're already merged - requiresMerging = false; - } else if (target.getEquivalence() != null) { - final Diff masterEquivalence = findMasterEquivalence(target, mergeRightToLeft); - if (masterEquivalence != null && masterEquivalence != target) { - // If we have a "master" equivalence (see doc on findMasterEquivalence) then we've been merged - // along with it - requiresMerging = false; - } else { - // We also need to check for implications on our equivalence (dependency loops) - requiresMerging = !hasTransitiveImplicationBeenMerged(target, mergeRightToLeft); + protected void copyDiff(Diff target, Monitor monitor, boolean rightToLeft) { + if (isInTerminalState(target)) { + return; + } + + long start = System.currentTimeMillis(); + + // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles. + target.setState(MERGING); + + // Mark all implied diffs as merged before actually merging this one + Set<Diff> impliedMerges = getImpliedMerges(target, rightToLeft); + while (!impliedMerges.isEmpty()) { + Diff impliedMerge = impliedMerges.iterator().next(); + // avoid implication circles + if (impliedMerge != target && !isInTerminalState(impliedMerge)) { + impliedMerge.setState(MERGED); + impliedMerges.addAll(getImpliedMerges(impliedMerge, rightToLeft)); } + impliedMerges.remove(impliedMerge); + impliedMerges.remove(target); + } + if (isAccepting(target, rightToLeft)) { + accept(target, rightToLeft); + } else { + reject(target, rightToLeft); + } + target.setState(MERGED); + + if (LOGGER.isDebugEnabled()) { + long duration = System.currentTimeMillis() - start; + LOGGER.debug("copyDiff(Diff, Monitor, Boolean) - diff " + target.hashCode() //$NON-NLS-1$ + + " merged (rightToLeft: " + rightToLeft + ") in " //$NON-NLS-1$ //$NON-NLS-2$ + + duration + "ms"); //$NON-NLS-1$ } - return requiresMerging; } /** - * Checks if the given diff is implied by another in the given merge direction, which means that it - * doesn't need to be merged individually. + * {@inheritDoc} * - * @param target - * The diff we're considering merging. - * @param mergeRightToLeft - * The direction in which we're currently merging. - * @return <code>true</code> if the given diff will be implicitely merged by another in that direction. + * @see org.eclipse.emf.compare.merge.IMerger#copyLeftToRight(org.eclipse.emf.compare.Diff, + * org.eclipse.emf.common.util.Monitor) + * @since 3.1 */ - private boolean isImpliedMerge(Diff target, boolean mergeRightToLeft) { - final boolean isImpliedForDirection; - if (mergeRightToLeft) { - if (DifferenceSource.LEFT == target.getSource()) { - isImpliedForDirection = !target.getImplies().isEmpty(); - } else { - isImpliedForDirection = !target.getImpliedBy().isEmpty(); - } - } else { - if (DifferenceSource.LEFT == target.getSource()) { - isImpliedForDirection = !target.getImpliedBy().isEmpty(); - } else { - isImpliedForDirection = !target.getImplies().isEmpty(); - } - } - return isImpliedForDirection; + public void copyLeftToRight(Diff target, Monitor monitor) { + copyDiff(target, monitor, false); } - // FIXME find a use case and check whether this is still required. /** - * Checks whether the given diff has been merged through a dependency cycle on its equivalence relations - * (this diff requires the merging of a diff that implies one of its equivalences). - * <p> - * This should only be called on differences that have equivalences. - * </p> + * {@inheritDoc} * - * @param target - * The difference we are considering merging. - * @param mergeRightToLeft - * The direction in which we're considering a merge. - * @return <code>true</code> if the <code>target</code> diff has already been merged. + * @see org.eclipse.emf.compare.merge.IMerger#copyRightToLeft(org.eclipse.emf.compare.Diff, + * org.eclipse.emf.common.util.Monitor) + * @since 3.1 */ - private boolean hasTransitiveImplicationBeenMerged(Diff target, boolean mergeRightToLeft) { - boolean mergedThroughEquivalentImplication = false; - final Iterator<Diff> equivalenceIterator = target.getEquivalence().getDifferences().iterator(); - while (!mergedThroughEquivalentImplication && equivalenceIterator.hasNext()) { - final Diff equivalent = equivalenceIterator.next(); - if (equivalent != target && mergeRightToLeft) { - if (target.getSource() == DifferenceSource.LEFT) { - mergedThroughEquivalentImplication = any(equivalent.getImplies(), - in(target.getRequiredBy())); - } else { - mergedThroughEquivalentImplication = any(equivalent.getImpliedBy(), - in(target.getRequires())); - } - } else if (equivalent != target) { - if (target.getSource() == DifferenceSource.LEFT) { - mergedThroughEquivalentImplication = any(equivalent.getImpliedBy(), - in(target.getRequires())); - } else { - mergedThroughEquivalentImplication = any(equivalent.getImplies(), - in(target.getRequiredBy())); - } - } - } - return mergedThroughEquivalentImplication; + public void copyRightToLeft(Diff target, Monitor monitor) { + copyDiff(target, monitor, true); } /** @@ -1095,6 +1017,25 @@ public abstract class AbstractMerger implements IMerger2, IMergeOptionAware, IMe } /** + * Returns whether the given difference is in a terminal state or not. Differences that are in a terminal + * state, i.e., either MERGED or DISCARDED, do not need to be handled by the merger. + * + * @param target + * difference + * @return true if the target should be merged, false otherwise. + * @since 3.5 + */ + public static boolean isInTerminalState(Diff target) { + switch (target.getState()) { + case MERGED: + case DISCARDED: + return true; + default: + return false; + } + } + + /** * Handles the equivalences of this difference. * <p> * Note that in certain cases, we'll merge our opposite instead of merging this diff. This is done to @@ -1155,21 +1096,12 @@ public abstract class AbstractMerger implements IMerger2, IMergeOptionAware, IMe * a merged diff, then we have a dependency loop : the "current" difference has already been * merged because of this implication. This will allow us to break out of that loop. */ - if (rightToLeft) { - if (diff.getSource() == DifferenceSource.LEFT) { - continueMerge = continueMerge && !any(equivalent.getImplies(), in(diff.getRequiredBy())); - } else { - continueMerge = continueMerge && !any(equivalent.getImpliedBy(), in(diff.getRequires())); - } + if (isAccepting(diff, rightToLeft)) { + continueMerge = continueMerge && !any(equivalent.getImpliedBy(), in(diff.getRequires())); } else { - if (diff.getSource() == DifferenceSource.LEFT) { - continueMerge = continueMerge && !any(equivalent.getImpliedBy(), in(diff.getRequires())); - } else { - continueMerge = continueMerge && !any(equivalent.getImplies(), in(diff.getRequiredBy())); - } + continueMerge = continueMerge && !any(equivalent.getImplies(), in(diff.getRequiredBy())); } - - equivalent.setState(DifferenceState.MERGED); + equivalent.setState(MERGED); } return continueMerge; } @@ -1242,7 +1174,7 @@ public abstract class AbstractMerger implements IMerger2, IMergeOptionAware, IMe * this will either "set" or "change" values... or if the given diff is affecting a multi-valued * reference. */ - private boolean isUnset(ReferenceChange diff, boolean mergeRightToLeft) { + protected boolean isUnset(ReferenceChange diff, boolean mergeRightToLeft) { if (diff.getKind() != DifferenceKind.CHANGE) { return false; } @@ -1259,12 +1191,12 @@ public abstract class AbstractMerger implements IMerger2, IMergeOptionAware, IMe if (container == null) { // This is an unset diff. However, if we're merging towards the source, we're actually "rejecting" // the unset, and the merge operation will be a "set" - isUnset = !isRejecting(diff, mergeRightToLeft); + isUnset = isAccepting(diff, mergeRightToLeft); } else { if (!ReferenceUtil.safeEIsSet(container, diff.getReference())) { // No value on the source side, this is an unset // Same case as above, if we are rejecting the diff, it is a "set" operation - isUnset = !isRejecting(diff, mergeRightToLeft); + isUnset = isAccepting(diff, mergeRightToLeft); } else { // The feature is set on the source side. If we're merging towards the other side, this cannot // be an unset. @@ -1299,8 +1231,9 @@ public abstract class AbstractMerger implements IMerger2, IMergeOptionAware, IMe * @return <code>true</code> if {@code diff} will set a value with this merge, <code>false</code> if this * will either "unset" or "change" values... or if the given diff is affecting a multi-valued * reference. + * @since 3.5 */ - private boolean isSet(ReferenceChange diff, boolean mergeRightToLeft) { + protected boolean isSet(ReferenceChange diff, boolean mergeRightToLeft) { if (diff.getKind() != DifferenceKind.CHANGE) { return false; } @@ -1358,6 +1291,33 @@ public abstract class AbstractMerger implements IMerger2, IMergeOptionAware, IMe } /** + * Checks whether the given merge direction will result in accepting this difference based on the + * difference's {@link Diff#getSource() source}. + * + * <pre> + * | LEFT | RIGHT + * --------------------+-------+------- + * Merge Left to Right | true | false + * Merge Right to Left | false | true + * </pre> + * + * @param diff + * difference + * @param mergeRightToLeft + * merge direction + * @return true if the merge source direction matches the difference source, false otherwise. + * @see #isRejecting(Diff, boolean) + * @since 3.5 + */ + public static boolean isAccepting(Diff diff, boolean mergeRightToLeft) { + if (diff.getSource() == RIGHT) { + return mergeRightToLeft; + } else { + return !mergeRightToLeft; + } + } + + /** * Checks whether the given merge direction will result in rejecting this difference. * * @param diff @@ -1365,13 +1325,10 @@ public abstract class AbstractMerger implements IMerger2, IMergeOptionAware, IMe * @param mergeRightToLeft * Direction of the merge operation. * @return <code>true</code> if we're rejecting this diff. + * @see #isAccepting(Diff, boolean) */ private boolean isRejecting(Diff diff, boolean mergeRightToLeft) { - if (diff.getSource() == DifferenceSource.LEFT) { - return mergeRightToLeft; - } else { - return !mergeRightToLeft; - } + return !isAccepting(diff, mergeRightToLeft); } /** diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AdditiveConflictMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AdditiveConflictMerger.java index e4c0e4009..d4c978fc3 100644 --- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AdditiveConflictMerger.java +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AdditiveConflictMerger.java @@ -14,15 +14,11 @@ 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.DifferenceState.MERGED; -import static org.eclipse.emf.compare.DifferenceState.UNRESOLVED; -import org.eclipse.emf.common.util.EList; +import java.util.Set; + import org.eclipse.emf.common.util.Monitor; -import org.eclipse.emf.compare.AttributeChange; -import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.Diff; -import org.eclipse.emf.compare.ReferenceChange; -import org.eclipse.emf.ecore.EObject; /** * This specific implementation of {@link AbstractMerger} will be used to merge conflicts in an additive merge @@ -48,32 +44,7 @@ public class AdditiveConflictMerger extends ConflictMerger { @Override public void copyRightToLeft(Diff target, Monitor monitor) { - if (target.getState() != UNRESOLVED) { - return; - } - - // We need to merge diffs in the conflict that are pseudo conflicting diffs. This behavior is required - // to bypass some behavior in AbstractMerger which is not aware of additive related behavior. - Comparison comparison = target.getMatch().getComparison(); - EList<Diff> rightDifferences = target.getConflict().getRightDifferences(); - for (Diff diff : rightDifferences) { - EList<Diff> differences = diff.getMatch().getDifferences(); - for (Diff diff2 : differences) { - if (isEquivalentFromDifferentSides(comparison, diff, diff2)) { - diff.setState(MERGED); - diff2.setState(MERGED); - } - } - } - - // get rid of refined diffs. - if (target.getSource() == RIGHT) { - for (Diff diff : target.getRefines()) { - getMergerDelegate(diff).copyRightToLeft(diff, monitor); - } - } - - if (target.getState() == MERGED) { + if (isInTerminalState(target)) { return; } @@ -89,39 +60,25 @@ public class AdditiveConflictMerger extends ConflictMerger { } } - /** - * Test if two given diffs are equivalent, i.e. if they weren't in a real conflicts they where detected as - * pseudo conflicts. - * - * @param comparison - * The comparison - * @param diff - * The first diff - * @param diff2 - * The second diff - * @return <code>true</code> if the diffs are equivalent - */ - private boolean isEquivalentFromDifferentSides(Comparison comparison, Diff diff, Diff diff2) { - if (diff.eClass() == diff2.eClass() && diff.getSource() != diff2.getSource()) { - if (diff.getKind() == diff2.getKind()) { - if (diff instanceof ReferenceChange) { - EObject value = ((ReferenceChange)diff).getValue(); - EObject value2 = ((ReferenceChange)diff2).getValue(); - if (value == null && value2 == null) { - return true; - } - if (comparison.getMatch(value) == comparison.getMatch(value2)) { - return true; - } - } else if (diff instanceof AttributeChange) { - if (((AttributeChange)diff).getValue() == ((AttributeChange)diff2).getValue()) { - return true; - } - } - } + @Override + public Set<Diff> getDirectMergeDependencies(Diff target, boolean mergeRightToLeft) { + if (target.getSource() == RIGHT && target.getKind() != DELETE) { + return super.getDirectMergeDependencies(target, mergeRightToLeft); + } else if (target.getSource() == LEFT && target.getKind() == DELETE) { + return super.getDirectMergeDependencies(target, mergeRightToLeft); + } else { + return super.getDirectMergeDependencies(target, !mergeRightToLeft); } - - return false; } + @Override + public Set<Diff> getDirectResultingMerges(Diff target, boolean mergeRightToLeft) { + if (target.getSource() == RIGHT && target.getKind() != DELETE) { + return super.getDirectResultingMerges(target, mergeRightToLeft); + } else if (target.getSource() == LEFT && target.getKind() == DELETE) { + return super.getDirectResultingMerges(target, mergeRightToLeft); + } else { + return super.getDirectResultingMerges(target, !mergeRightToLeft); + } + } } diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AdditiveReferenceChangeMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AdditiveReferenceChangeMerger.java index 5a7e33542..5f181c98a 100644 --- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AdditiveReferenceChangeMerger.java +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AdditiveReferenceChangeMerger.java @@ -14,7 +14,8 @@ 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.DifferenceState.MERGED; -import static org.eclipse.emf.compare.DifferenceState.UNRESOLVED; + +import java.util.Set; import org.eclipse.emf.common.util.Monitor; import org.eclipse.emf.compare.Diff; @@ -48,7 +49,7 @@ public class AdditiveReferenceChangeMerger extends ReferenceChangeMerger { @Override public void copyRightToLeft(Diff target, Monitor monitor) { - if (target.getState() != UNRESOLVED) { + if (isInTerminalState(target)) { return; } @@ -127,18 +128,86 @@ public class AdditiveReferenceChangeMerger extends ReferenceChangeMerger { } /** - * Mark a diff and its required diffs as merged. + * Mark a diff and its refining diffs as merged. * * @param diff * The diff to merge */ private void markAsMerged(Diff diff) { - // diff.setState(MERGED); diff.setState(MERGED); for (Diff refiningDiff : diff.getRefinedBy()) { - // markAsMerged(refiningDiff); refiningDiff.setState(MERGED); } } + // CHECKSTYLE:OFF + @Override + public Set<Diff> getDirectMergeDependencies(Diff diff, boolean mergeRightToLeft) { + ReferenceChange rc = (ReferenceChange)diff; + if (rc.getReference().isContainment()) { + if (rc.getSource() == RIGHT) { + if (rc.getKind() == DELETE) { + return super.getDirectMergeDependencies(diff, !mergeRightToLeft); + } else { + return super.getDirectMergeDependencies(diff, mergeRightToLeft); + } + } else { + if (rc.getKind() == DELETE) { + return super.getDirectMergeDependencies(diff, mergeRightToLeft); + } else { + return super.getDirectMergeDependencies(diff, !mergeRightToLeft); + } + } + } else { + if (rc.getSource() == RIGHT) { + if (rc.getKind() == DELETE || isUnsetRelatedToDeletion(rc)) { + return super.getDirectMergeDependencies(diff, !mergeRightToLeft); + } else { + return super.getDirectMergeDependencies(diff, mergeRightToLeft); + } + } else { + if (rc.getKind() == DELETE || isUnsetRelatedToDeletion(rc)) { + return super.getDirectMergeDependencies(diff, mergeRightToLeft); + } else { + return super.getDirectMergeDependencies(diff, !mergeRightToLeft); + } + } + } + } + + @Override + public Set<Diff> getDirectResultingMerges(Diff diff, boolean mergeRightToLeft) { + ReferenceChange rc = (ReferenceChange)diff; + if (rc.getReference().isContainment()) { + if (rc.getSource() == RIGHT) { + if (rc.getKind() == DELETE) { + return super.getDirectResultingMerges(diff, !mergeRightToLeft); + } else { + return super.getDirectResultingMerges(diff, mergeRightToLeft); + } + } else { + if (rc.getKind() == DELETE) { + return super.getDirectResultingMerges(diff, mergeRightToLeft); + } else { + return super.getDirectResultingMerges(diff, !mergeRightToLeft); + } + } + } else { + if (rc.getSource() == RIGHT) { + if (rc.getKind() == DELETE || isUnsetRelatedToDeletion(rc)) { + return super.getDirectResultingMerges(diff, !mergeRightToLeft); + } else { + return super.getDirectResultingMerges(diff, mergeRightToLeft); + } + } else { + if (rc.getKind() == DELETE || isUnsetRelatedToDeletion(rc)) { + return super.getDirectResultingMerges(diff, mergeRightToLeft); + } else { + return super.getDirectResultingMerges(diff, !mergeRightToLeft); + } + } + } + } + + // CHECKSTYLE:ON } diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AdditiveResourceAttachmentChangeMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AdditiveResourceAttachmentChangeMerger.java index 98411cbc2..57e3925f7 100644 --- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AdditiveResourceAttachmentChangeMerger.java +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AdditiveResourceAttachmentChangeMerger.java @@ -13,7 +13,8 @@ package org.eclipse.emf.compare.merge; import static org.eclipse.emf.compare.DifferenceKind.DELETE; import static org.eclipse.emf.compare.DifferenceSource.LEFT; import static org.eclipse.emf.compare.DifferenceState.MERGED; -import static org.eclipse.emf.compare.DifferenceState.UNRESOLVED; + +import java.util.Set; import org.eclipse.emf.common.util.Monitor; import org.eclipse.emf.compare.Diff; @@ -42,7 +43,7 @@ public class AdditiveResourceAttachmentChangeMerger extends ResourceAttachmentCh @Override public void copyRightToLeft(Diff target, Monitor monitor) { - if (target.getState() != UNRESOLVED) { + if (isInTerminalState(target)) { return; } @@ -60,4 +61,29 @@ public class AdditiveResourceAttachmentChangeMerger extends ResourceAttachmentCh } } + @Override + public Set<Diff> getDirectMergeDependencies(Diff diff, boolean mergeRightToLeft) { + if (diff.getKind() == DELETE) { + if (diff.getSource() == LEFT) { + return super.getDirectMergeDependencies(diff, mergeRightToLeft); + } else { + return super.getDirectMergeDependencies(diff, !mergeRightToLeft); + } + } else { + return super.getDirectMergeDependencies(diff, mergeRightToLeft); + } + } + + @Override + public Set<Diff> getDirectResultingMerges(Diff diff, boolean mergeRightToLeft) { + if (diff.getKind() == DELETE) { + if (diff.getSource() == LEFT) { + return super.getDirectResultingMerges(diff, mergeRightToLeft); + } else { + return super.getDirectResultingMerges(diff, !mergeRightToLeft); + } + } else { + return super.getDirectResultingMerges(diff, mergeRightToLeft); + } + } } diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/BatchMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/BatchMerger.java index cacf2b29b..b49795edd 100644 --- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/BatchMerger.java +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/BatchMerger.java @@ -16,10 +16,11 @@ import static com.google.common.base.Predicates.alwaysTrue; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; +import java.util.Set; + import org.apache.log4j.Logger; import org.eclipse.emf.common.util.Monitor; import org.eclipse.emf.compare.Diff; -import org.eclipse.emf.compare.DifferenceState; /** * This implementation of an {@link IBatchMerger} leaves some choice to the client as to what should be @@ -34,7 +35,7 @@ public class BatchMerger implements IBatchMerger { private static final Logger LOGGER = Logger.getLogger(BatchMerger.class); /** The registry from which we'll retrieve our mergers. */ - private final IMerger.Registry registry; + private final IMerger.Registry2 registry; /** Filter the differences that should be merged. */ private final Predicate<? super Diff> filter; @@ -44,7 +45,8 @@ public class BatchMerger implements IBatchMerger { * such a merger will merge every differences passed to its "copy" methods : conflictual or not. * * @param registry - * The registry from which we'll retrieve delegate mergers. + * The registry from which we'll retrieve delegate mergers, must be an instance of + * IMerger.Registry2. */ public BatchMerger(IMerger.Registry registry) { this(registry, alwaysTrue()); @@ -67,7 +69,8 @@ public class BatchMerger implements IBatchMerger { * </p> * * @param registry - * The registry from which we'll retrieve delegate mergers. + * The registry from which we'll retrieve delegate mergers, must be an instance of + * IMerger.Registry2. * @param filter * Additional filter for the differences. This could be set in order to ignore diffs * originating from a given side. Note that the filter describes the differences that will be @@ -76,7 +79,7 @@ public class BatchMerger implements IBatchMerger { * @see org.eclipse.emf.compare.utils.EMFComparePredicates */ public BatchMerger(IMerger.Registry registry, Predicate<? super Diff> filter) { - this.registry = checkNotNull(registry); + this.registry = (IMerger.Registry2)checkNotNull(registry); this.filter = checkNotNull(filter); } @@ -92,26 +95,19 @@ public class BatchMerger implements IBatchMerger { start = System.currentTimeMillis(); LOGGER.debug("copyAllLeftToRight(differences, monitor) - Start"); //$NON-NLS-1$ } - if (filter == alwaysTrue()) { - for (Diff diff : differences) { - if (diff.getState() != DifferenceState.MERGED) { - final IMerger merger = registry.getHighestRankingMerger(diff); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("copyAllLeftToRight - Selected merger: " //$NON-NLS-1$ - + merger.getClass().getSimpleName()); - } - merger.copyLeftToRight(diff, monitor); - } - } - } else { - for (Diff diff : Iterables.filter(differences, filter)) { - if (diff.getState() != DifferenceState.MERGED) { - final IMerger merger = registry.getHighestRankingMerger(diff); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("copyAllLeftToRight - Selected merger: " //$NON-NLS-1$ - + merger.getClass().getSimpleName()); + ComputeDiffsToMerge computer = new ComputeDiffsToMerge(false, registry); + for (Diff diff : Iterables.filter(differences, filter)) { + if (!AbstractMerger.isInTerminalState(diff)) { + Set<Diff> diffsToMerge = computer.getAllDiffsToMerge(diff); + for (Diff toMerge : diffsToMerge) { + if (!AbstractMerger.isInTerminalState(toMerge)) { + final IMerger merger = registry.getHighestRankingMerger(toMerge); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("copyAllLeftToRight - Selected merger: " //$NON-NLS-1$ + + merger.getClass().getSimpleName()); + } + merger.copyLeftToRight(toMerge, monitor); } - merger.copyLeftToRight(diff, monitor); } } } @@ -133,26 +129,19 @@ public class BatchMerger implements IBatchMerger { start = System.currentTimeMillis(); LOGGER.debug("copyAllRightToLeft(differences, monitor) - Start"); //$NON-NLS-1$ } - if (filter == alwaysTrue()) { - for (Diff diff : differences) { - if (diff.getState() != DifferenceState.MERGED) { - final IMerger merger = registry.getHighestRankingMerger(diff); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("copyAllRightToLeft - Selected merger: " //$NON-NLS-1$ - + merger.getClass().getSimpleName()); - } - merger.copyRightToLeft(diff, monitor); - } - } - } else { - for (Diff diff : Iterables.filter(differences, filter)) { - if (diff.getState() != DifferenceState.MERGED) { - final IMerger merger = registry.getHighestRankingMerger(diff); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("copyAllRightToLeft - Selected merger: " //$NON-NLS-1$ - + merger.getClass().getSimpleName()); + ComputeDiffsToMerge computer = new ComputeDiffsToMerge(true, registry); + for (Diff diff : Iterables.filter(differences, filter)) { + if (!AbstractMerger.isInTerminalState(diff)) { + Set<Diff> diffsToMerge = computer.getAllDiffsToMerge(diff); + for (Diff toMerge : diffsToMerge) { + if (!AbstractMerger.isInTerminalState(toMerge)) { + final IMerger merger = registry.getHighestRankingMerger(toMerge); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("copyAllLeftToRight - Selected merger: " //$NON-NLS-1$ + + merger.getClass().getSimpleName()); + } + merger.copyRightToLeft(toMerge, monitor); } - merger.copyRightToLeft(diff, monitor); } } } 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 new file mode 100644 index 000000000..02b569291 --- /dev/null +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ComputeDiffsToMerge.java @@ -0,0 +1,197 @@ +/******************************************************************************* + * Copyright (c) 2017 Obeo. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.emf.compare.merge; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.eclipse.emf.compare.ConflictKind.REAL; +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; +import org.eclipse.emf.compare.Diff; + +/** + * This class computes the diffs to merge for a given diff in the correct order, taking into account the + * merger's indications about required and consequent diffs. + * <dl> + * <dt>Required diffs</dt> + * <dd>These are the diffs that need to be merged (from a structural point of view) before a given diff for + * this diff to be mergeabl by th merger.</dd> + * <dt>Consequent diffs</dt> + * <dd>These are all the diffs that, for some reason, the merger considers necessary to merge along with a + * given diff, but which need not be merged before this diff for the merger to be able to merge it. This is + * used to define atomicity of merge operations: Each merger defines the set of diffs that must be merged + * together, and the engine makes surre all these diffs (required+consequent) are merged together or not at + * all in one 'transaction'.</dd> + * </dl> + * + * @author <a href="mailto:laurent.delaigue@obeo.fr">Laurent Delaigue</a> + * @since 3.5 + */ +public class ComputeDiffsToMerge { + + /** + * The direction of the merge, <code>true</code> for right to left. + */ + private final boolean rightToLeft; + + /** + * The merge criterion to use, can be <code>null</code>. + */ + private IMergeCriterion criterion; + + /** + * The merger registry to use. + */ + private IMerger.Registry2 registry; + + /** + * The ordered set of diffs to merge. + */ + private Set<Diff> result = new LinkedHashSet<Diff>(); + + /** The unordered set of all diffs used to avoid infinite loops. */ + private Set<Diff> computing = new HashSet<Diff>(); + + /** + * Whether the discovery of a (real) conflict in the differences needed must cause this to throw an + * Exception. + */ + private Predicate<? super Conflict> conflictChecker; + + /** + * Constructor. + * + * @param rightToLeft + * The merge direction + * @param registry + * The Registry to use. + */ + public ComputeDiffsToMerge(boolean rightToLeft, IMerger.Registry2 registry) { + this(rightToLeft, registry, NONE); + } + + /** + * Constructor. + * + * @param rightToLeft + * The merge direction + * @param registry + * The Registry to use. + * @param criterion + * The merge criterion, must not be <code>null</code> + */ + public ComputeDiffsToMerge(boolean rightToLeft, IMerger.Registry2 registry, IMergeCriterion criterion) { + this.rightToLeft = rightToLeft; + this.registry = registry; + this.criterion = checkNotNull(criterion); + } + + /** + * Set the failOnConflict flag. + * + * @param predicate + * Predicate that will be used to check whether an exception must be thrown when encountering a + * diff that's involved in a conflict. This predicate will be applied to the conflict, and if + * it returns <code>false</code> then an exception will be thrown. + * @return This for a fluent API. + */ + public ComputeDiffsToMerge failOnRealConflictUnless(Predicate<? super Conflict> predicate) { + conflictChecker = predicate; + return this; + } + + /** + * Compute the ordered set of diffs to merge for the given diff. + * + * @param diff + * The diff to merge, along with its required diffs and its consequent diffs. + * @return An ordered Set that contains all the diffs to merge, in the correct order. + */ + public Set<Diff> getAllDiffsToMerge(Diff diff) { + result.clear(); + computing.clear(); + addDiff(diff); + return result; + } + + /** + * Compute the ordered set of diffs for the given diff. + * + * @param diff + * The diff to merge + */ + protected void addDiff(Diff diff) { + addDiffs(Collections.singleton(diff)); + } + + /** + * Recursively add the given diffs to the result Set, starting by their requirements, then themselves, + * then their consequences, in the right order. + * + * @param diffs + * The diffs to merge at the current step of the computation + */ + protected void addDiffs(Collection<Diff> diffs) { + if (diffs.isEmpty()) { + return; + } + Set<Diff> consequences = new LinkedHashSet<Diff>(); + for (Diff diff : diffs) { + addDiff(diff, consequences); + } + addDiffs(Sets.difference(consequences, result)); + } + + /** + * Recursively add the required diffs, then the diff itself, to the result. Also add the consequent diffs + * of all the required diffs and the provided one to the given set of consequences. + * + * @param diff + * The diff to add + * @param consequences + * The set of diffs that must be merged at the next step. + */ + protected void addDiff(Diff diff, Set<Diff> consequences) { + if (!result.contains(diff) && computing.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); + } + DelegatingMerger mergerDelegate = AbstractMerger.getMergerDelegate(diff, registry, criterion); + IMerger merger = mergerDelegate.getMerger(); + if (merger instanceof IMerger2) { + Set<Diff> dependencies = ((IMerger2)merger).getDirectMergeDependencies(diff, rightToLeft); + for (Diff required : dependencies) { + addDiff(required, consequences); + } + result.add(diff); + computing.remove(diff); + consequences.addAll(((IMerger2)merger).getDirectResultingMerges(diff, rightToLeft)); + } else { + result.add(diff); + } + } + } +} diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ConflictMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ConflictMerger.java index 9ac9acea9..c2038e3de 100644 --- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ConflictMerger.java +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ConflictMerger.java @@ -16,9 +16,10 @@ import static org.eclipse.emf.compare.DifferenceKind.MOVE; import static org.eclipse.emf.compare.DifferenceSource.LEFT; import static org.eclipse.emf.compare.DifferenceSource.RIGHT; import static org.eclipse.emf.compare.DifferenceState.MERGED; -import static org.eclipse.emf.compare.DifferenceState.UNRESOLVED; +import static org.eclipse.emf.compare.merge.IMergeCriterion.NONE; import java.util.Iterator; +import java.util.Set; import org.eclipse.emf.common.util.Monitor; import org.eclipse.emf.compare.Conflict; @@ -45,7 +46,7 @@ public class ConflictMerger extends AbstractMerger { @Override public boolean apply(IMergeCriterion criterion) { - return criterion == null; + return criterion == null || criterion == NONE; } /** @@ -56,8 +57,7 @@ public class ConflictMerger extends AbstractMerger { */ @Override public void copyLeftToRight(Diff target, Monitor monitor) { - // Don't merge an already merged (or discarded) diff - if (target.getState() != UNRESOLVED) { + if (isInTerminalState(target)) { return; } @@ -88,8 +88,7 @@ public class ConflictMerger extends AbstractMerger { */ @Override public void copyRightToLeft(Diff target, Monitor monitor) { - // Don't merge an already merged (or discarded) diff - if (target.getState() != UNRESOLVED) { + if (isInTerminalState(target)) { return; } @@ -111,6 +110,40 @@ public class ConflictMerger extends AbstractMerger { getMergerDelegate(target).copyRightToLeft(target, monitor); } + @Override + public Set<Diff> getDirectMergeDependencies(Diff diff, boolean rightToLeft) { + Set<Diff> result = super.getDirectMergeDependencies(diff, rightToLeft); + // Add each conflicting diff from the other side + Conflict conflict = diff.getConflict(); + if (AbstractMerger.isAccepting(diff, rightToLeft)) { + for (Diff conflictingDiff : conflict.getDifferences()) { + if (conflictingDiff.getSource() != diff.getSource() + && !isConflictVsMoveAndDelete(conflictingDiff, diff, !rightToLeft) + && conflictingDiff.getKind() != MOVE) { + result.add(conflictingDiff); + } + } + } + return result; + } + + @Override + public Set<Diff> getDirectResultingMerges(Diff diff, boolean rightToLeft) { + Set<Diff> result = super.getDirectResultingMerges(diff, rightToLeft); + + Conflict conflict = diff.getConflict(); + if (AbstractMerger.isAccepting(diff, rightToLeft)) { + for (Diff conflictingDiff : conflict.getDifferences()) { + if (conflictingDiff.getSource() != diff.getSource() + && (isConflictVsMoveAndDelete(conflictingDiff, diff, !rightToLeft) + || conflictingDiff.getKind() != MOVE)) { + result.add(conflictingDiff); + } + } + } + return result; + } + /** * Detect if the two given diff are diffs on the same object with one move and one delete. The move diff * must be the one selected by the user for merging. @@ -166,8 +199,8 @@ public class ConflictMerger extends AbstractMerger { @Override protected DelegatingMerger getMergerDelegate(Diff diff) { - IMergeCriterion criterion = (IMergeCriterion)getMergeOptions().get( - IMergeCriterion.OPTION_MERGE_CRITERION); + IMergeCriterion criterion = (IMergeCriterion)getMergeOptions() + .get(IMergeCriterion.OPTION_MERGE_CRITERION); Iterator<IMerger> it = ((Registry2)getRegistry()).getMergersByRankDescending(diff, criterion); IMerger merger = this; while (it.hasNext() && merger == this) { diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMergeCriterion.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMergeCriterion.java index 1545bcebc..170ffdf26 100644 --- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMergeCriterion.java +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMergeCriterion.java @@ -24,4 +24,10 @@ public interface IMergeCriterion { * mergers can propagate the criterion to the mergers they may invoke. */ String OPTION_MERGE_CRITERION = "merge.criterion"; //$NON-NLS-1$ + + /** + * Default criterion that means that no special criterion is set. + */ + IMergeCriterion NONE = new IMergeCriterion() { + }; } diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMerger2.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMerger2.java index f2587a8a3..278979229 100644 --- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMerger2.java +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMerger2.java @@ -31,21 +31,23 @@ import org.eclipse.emf.compare.Diff; */ public interface IMerger2 extends IMerger { /** - * Retrieves the set of <b>directly</b> required diffs in order to merge the current one. This may - * includes the diff's {@link Diff#getRequires() requirements}, its {@link Diff#getImpliedBy() implying - * diff}, or any other diff that we need to merge <u>before</u> the given one. + * Retrieves the set of <b>directly</b> required diffs needed in order to merge the current one. This may + * includes the diff's {@link Diff#getRequires() requirements} or any other diff that we need to merge + * <u>before</u> the given one. * * @param diff * The diff which direct requirements we need. - * @param mergeLeftToRight + * @param mergeRightToLeft * The direction in which we're considering a merge. * @return The set of <b>directly</b> required diffs in order to merge the current one. */ - Set<Diff> getDirectMergeDependencies(Diff diff, boolean mergeLeftToRight); + Set<Diff> getDirectMergeDependencies(Diff diff, boolean mergeRightToLeft); /** * Returns all differences that will be merged because of our merging the given <code>target</code> - * difference. + * difference. This may include the diff's {@link Diff#getImplies() implications}, the diff's + * {@link Diff#getEquivalence() equivalences}, the diff's {@link Diff#getRefines() refinements} or any + * other diff that we need to merge <u>together</u> with the given diff. * * @param target * The difference we're considering merging. diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/MergeBlockedByConflictException.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/MergeBlockedByConflictException.java new file mode 100644 index 000000000..e45c445d0 --- /dev/null +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/MergeBlockedByConflictException.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2017 Obeo. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.emf.compare.merge; + +import java.util.Collection; + +import org.eclipse.emf.compare.Diff; + +/** + * Exception that indicates that a merge cannot be performed because it would lead to involuntarily resolving + * a conflict. + * + * @author <a href="mailto:laurent.delaigue@obeo.fr">Laurent Delaigue</a> + * @since 3.5 + */ +public class MergeBlockedByConflictException extends RuntimeException { + + /** Serial version UID. */ + private static final long serialVersionUID = -8395528878410874955L; + + /** The conflicting diffs. */ + private final Collection<Diff> conflictingDiffs; + + /** + * Constructor. + * + * @param conflictingDiffs + * The diffs that depend on a conflict + */ + public MergeBlockedByConflictException(Collection<Diff> conflictingDiffs) { + this.conflictingDiffs = conflictingDiffs; + } + + /** + * Get the conflicting diffs. + * + * @return The conflicting diffs. + */ + public Collection<Diff> getConflictingDiffs() { + return conflictingDiffs; + } + +} diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ReferenceChangeMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ReferenceChangeMerger.java index 65fad8fc4..f25563708 100644 --- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ReferenceChangeMerger.java +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ReferenceChangeMerger.java @@ -12,6 +12,7 @@ package org.eclipse.emf.compare.merge; import static com.google.common.collect.Iterators.filter; +import static org.eclipse.emf.compare.merge.IMergeCriterion.NONE; import static org.eclipse.emf.compare.utils.ReferenceUtil.safeEGet; import static org.eclipse.emf.compare.utils.ReferenceUtil.safeEIsSet; import static org.eclipse.emf.compare.utils.ReferenceUtil.safeESet; @@ -55,7 +56,7 @@ public class ReferenceChangeMerger extends AbstractMerger { @Override public boolean apply(IMergeCriterion criterion) { - return criterion == null; + return criterion == null || criterion == NONE; } /** @@ -393,9 +394,8 @@ public class ReferenceChangeMerger extends AbstractMerger { } if (expectedContainer == null) { - // FIXME throw exception? log? re-try to merge our requirements? - // one of the "required" diffs should have created our container. - return; + throw new IllegalStateException( + "Couldn't add in target because its parent hasn't been merged yet: " + diff); //$NON-NLS-1$ } final Comparison comparison = match.getComparison(); @@ -494,9 +494,8 @@ public class ReferenceChangeMerger extends AbstractMerger { final Match valueMatch = comparison.getMatch(diff.getValue()); if (currentContainer == null) { - // FIXME throw exception? log? re-try to merge our requirements? - // one of the "required" diffs should have created our container. - return; + throw new IllegalStateException( + "Couldn't add in target because its parent hasn't been merged yet: " + diff); //$NON-NLS-1$ } final EObject expectedValue; @@ -604,18 +603,10 @@ public class ReferenceChangeMerger extends AbstractMerger { protected void checkImpliedDiffsOrdering(ReferenceChange diff, boolean rightToLeft) { final EReference reference = diff.getReference(); final List<Diff> mergedImplications; - if (rightToLeft) { - if (diff.getSource() == DifferenceSource.LEFT) { - mergedImplications = diff.getImpliedBy(); - } else { - mergedImplications = diff.getImplies(); - } + if (isAccepting(diff, rightToLeft)) { + mergedImplications = diff.getImplies(); } else { - if (diff.getSource() == DifferenceSource.LEFT) { - mergedImplications = diff.getImplies(); - } else { - mergedImplications = diff.getImpliedBy(); - } + mergedImplications = diff.getImpliedBy(); } Iterator<Diff> impliedDiffs = mergedImplications.iterator(); @@ -629,6 +620,7 @@ public class ReferenceChangeMerger extends AbstractMerger { if (implied != diff && implied.getState() == DifferenceState.MERGED) { if (implied.getReference().isMany() && isAdd(implied, rightToLeft)) { internalCheckOrdering(implied, rightToLeft); + checkImpliedDiffsOrdering(implied, rightToLeft); } } } diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ResourceAttachmentChangeMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ResourceAttachmentChangeMerger.java index b8a7bfde4..25605ff23 100644 --- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ResourceAttachmentChangeMerger.java +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ResourceAttachmentChangeMerger.java @@ -12,6 +12,8 @@ *******************************************************************************/ package org.eclipse.emf.compare.merge; +import static org.eclipse.emf.compare.merge.IMergeCriterion.NONE; + import java.io.IOException; import java.util.Collections; import java.util.List; @@ -52,7 +54,7 @@ public class ResourceAttachmentChangeMerger extends AbstractMerger { @Override public boolean apply(IMergeCriterion criterion) { - return criterion == null; + return criterion == null || criterion == NONE; } /** 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 070ecd6c2..56d266466 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 @@ -22,6 +22,7 @@ import static com.google.common.collect.Iterables.any; import static org.eclipse.emf.compare.ConflictKind.PSEUDO; import static org.eclipse.emf.compare.ConflictKind.REAL; import static org.eclipse.emf.compare.DifferenceKind.ADD; +import static org.eclipse.emf.compare.DifferenceKind.DELETE; import static org.eclipse.emf.compare.internal.utils.ComparisonUtil.isDeleteOrUnsetDiff; import static org.eclipse.emf.compare.internal.utils.DiffUtil.getAllAtomicRefiningDiffs; import static org.eclipse.emf.compare.internal.utils.DiffUtil.getAllRefiningDiffs; @@ -32,6 +33,7 @@ import java.util.Arrays; import java.util.Iterator; import java.util.Set; +import org.eclipse.emf.common.util.EList; import org.eclipse.emf.compare.AttributeChange; import org.eclipse.emf.compare.Conflict; import org.eclipse.emf.compare.ConflictKind; @@ -42,6 +44,7 @@ import org.eclipse.emf.compare.DifferenceState; import org.eclipse.emf.compare.FeatureMapChange; import org.eclipse.emf.compare.Match; import org.eclipse.emf.compare.ReferenceChange; +import org.eclipse.emf.compare.ResourceAttachmentChange; import org.eclipse.emf.compare.ResourceLocationChange; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EGenericType; @@ -1267,6 +1270,16 @@ public final class EMFComparePredicates { } /** + * Predicate to test whether a conflict is additive or not. + * + * @return A predicate that returns <code>true</code> for additive conflicts. + * @since 3.5 + */ + public static Predicate<Conflict> isAdditiveConflict() { + return IsAdditive.INSTANCE; + } + + /** * 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. * @@ -1571,4 +1584,93 @@ public final class EMFComparePredicates { } } + /** + * Predicate to test whether a conflict is additive or not. A conflict is additive if it is REAL and at + * least one of its diffs is a containment deletion or is required by a containment deletion. + * + * @author <a href="mailto:laurent.delaigue@obeo.fr">Laurent Delaigue</a> + */ + private static final class IsAdditive implements Predicate<Conflict> { + /** The singleton instance of this predicate. */ + private static final IsAdditive INSTANCE = new IsAdditive(); + + /** + * Apply the predicate. + * + * @param conflict + * The conflict to test + * @return <code>true</code> if the conflict is additive. + */ + public boolean apply(Conflict conflict) { + return conflict.getKind() == REAL && hasContainmentDeletion(conflict.getDifferences()); + } + + /** + * Test a list of diff representing one side of a conflict to determine if we are in an additive + * conflict configuration. + * + * @param diffs + * A list of diffs from one side of a conflict + * @return <code>true</code> if there is a deletion of a containment reference or of a root node. + */ + private boolean hasContainmentDeletion(EList<Diff> diffs) { + for (Diff diff : diffs) { + if (isContainmentDelete(diff)) { + return true; + } + } + return false; + } + + /** + * Check whether a diff is a containment delete (either a DELETE ReferenceChange of a containment + * reference, or a DELETE ResourceAttachmentChange of a root EObject) or is required by a containment + * delete. + * + * @param diff + * The difference to test + * @return <code>true</code> if the given diff represents a containment deletion. + */ + private boolean isContainmentDelete(Diff diff) { + if (diff instanceof ReferenceChange) { + ReferenceChange rc = (ReferenceChange)diff; + if (rc.getReference().isContainment() && isRequiredByDeletion(rc)) { + return true; + } + } else if (diff instanceof ResourceAttachmentChange) { + ResourceAttachmentChange rac = (ResourceAttachmentChange)diff; + if (rac.getKind() == DELETE) { + Match match = rac.getMatch(); + EObject origin = match.getOrigin(); + // A ResourceAttachmentChange indicates the deletion of a root object only if its origin + // value is non-null and has no eContainer. + if (origin != null && origin.eContainer() == null) { + return true; + } + } + } + return false; + } + + /** + * Test if a diff or one of the diffs that require it are delete diffs. + * + * @param diff + * The given diff + * @return <code>true</code> if the diff or one of the diff that require it is a deletion. + */ + private boolean isRequiredByDeletion(Diff diff) { + if (diff.getKind() == DELETE) { + return true; + } else { + EList<Diff> requiredBy = diff.getRequiredBy(); + for (Diff requiredDiff : requiredBy) { + if (isRequiredByDeletion(requiredDiff)) { + return true; + } + } + } + return false; + } + } } |