[462884] Allows merging specific diffs in MergeAllNonConflictingRunnable

Renames MergeAllNonConflictingRunnable to MergeNonConflictingRunnable,
as it now allows to also merge a specific set of differences with the
same strategy as for all non-conflicting differences. Therefore, this
runnable now also implements IMergeRunnable.

Accordingly, also the test class for MergeNonConflictingRunnable have
been extended concerning the use cases for merging a given list of
differences only.

Also we introduce additional two-way tests in MergeAllCommandTests.

Bug: 462884
Change-Id: I80518d479db18c19bd51ebdabe5789ca58850672
Signed-off-by: Philip Langer <planger@eclipsesource.com>
diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/command/MergeAllCommandTests.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/command/MergeAllCommandTests.java
index 21a169c..57aea71 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/command/MergeAllCommandTests.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/command/MergeAllCommandTests.java
@@ -7,6 +7,7 @@
  * 
  * Contributors:
  *     Obeo - initial API and implementation
+ *     Philip Langer - 
  *******************************************************************************/
 package org.eclipse.emf.compare.ide.ui.tests.command;
 
@@ -33,7 +34,7 @@
 import org.eclipse.emf.compare.EMFCompare;
 import org.eclipse.emf.compare.command.impl.MergeAllNonConflictingCommand;
 import org.eclipse.emf.compare.domain.impl.EMFCompareEditingDomain;
-import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeAllNonConflictingRunnable;
+import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeNonConflictingRunnable;
 import org.eclipse.emf.compare.ide.ui.tests.command.data.MergeAllCommandInputData;
 import org.eclipse.emf.compare.internal.merge.MergeMode;
 import org.eclipse.emf.compare.merge.IMerger;
@@ -41,38 +42,48 @@
 import org.eclipse.emf.compare.scope.IComparisonScope;
 import org.eclipse.emf.ecore.change.util.ChangeRecorder;
 import org.eclipse.emf.ecore.resource.Resource;
+import org.junit.Before;
 import org.junit.Test;
 
 @SuppressWarnings({"restriction", "unchecked" })
 public class MergeAllCommandTests {
 
-	private MergeAllCommandInputData input = new MergeAllCommandInputData();
+	private Resource leftResource;
 
-	private final IMerger.Registry mergerRegistry = IMerger.RegistryImpl.createStandaloneInstance();
+	private Resource rightResource;
+
+	private Resource originResource;
+
+	private IMerger.Registry mergerRegistry;
+
+	@Before
+	public void getInputData() throws IOException {
+		final MergeAllCommandInputData input = new MergeAllCommandInputData();
+		leftResource = input.getLeftScope();
+		rightResource = input.getRightScope();
+		originResource = input.getOriginScope();
+		mergerRegistry = IMerger.RegistryImpl.createStandaloneInstance();
+	}
 
 	@Test
-	public void testMergeAllNonConflictingFromLeftToRight() throws IOException {
+	public void testMergeAllNonConflictingFromLeftToRightThreeWayWithoutConflicts() throws IOException {
 		MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
 		boolean leftToRight = true;
 		boolean isLeftEditable = true;
 		boolean isRightEditable = true;
 
-		Resource left = input.getLeftScope();
-		Resource right = input.getRightScope();
-		Resource origin = input.getOriginScope();
-
-		IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+		IComparisonScope scope = new DefaultComparisonScope(leftResource, rightResource, originResource);
 		Comparison comparison = EMFCompare.builder().build().compare(scope);
 
-		EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(left,
-				right, origin);
+		EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(
+				leftResource, rightResource, originResource);
 		ChangeRecorder changeRecorder = editingDomain.getChangeRecorder();
 
 		ImmutableSet.Builder<Notifier> notifiersBuilder = ImmutableSet.builder();
 		ImmutableSet<Notifier> notifiers = notifiersBuilder.add(comparison).addAll(
-				ImmutableList.of(left, right, origin)).build();
+				ImmutableList.of(leftResource, rightResource, originResource)).build();
 
-		MergeAllNonConflictingRunnable runnable = new MergeAllNonConflictingRunnable(isLeftEditable,
+		MergeNonConflictingRunnable runnable = new MergeNonConflictingRunnable(isLeftEditable,
 				isRightEditable, mergeMode);
 
 		MergeAllNonConflictingCommand command = new MergeAllNonConflictingCommand(changeRecorder, notifiers,
@@ -124,28 +135,24 @@
 	}
 
 	@Test
-	public void testMergeAllNonConflictingFromRightToLeft() throws IOException {
+	public void testMergeAllNonConflictingFromRightToLeftThreeWayWithoutConflicts() throws IOException {
 		MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
 		boolean leftToRight = false;
 		boolean isLeftEditable = true;
 		boolean isRightEditable = true;
 
-		Resource left = input.getLeftScope();
-		Resource right = input.getRightScope();
-		Resource origin = input.getOriginScope();
-
-		IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+		IComparisonScope scope = new DefaultComparisonScope(leftResource, rightResource, originResource);
 		Comparison comparison = EMFCompare.builder().build().compare(scope);
 
-		EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(left,
-				right, origin);
+		EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(
+				leftResource, rightResource, originResource);
 		ChangeRecorder changeRecorder = editingDomain.getChangeRecorder();
 
 		ImmutableSet.Builder<Notifier> notifiersBuilder = ImmutableSet.builder();
 		ImmutableSet<Notifier> notifiers = notifiersBuilder.add(comparison).addAll(
-				ImmutableList.of(left, right, origin)).build();
+				ImmutableList.of(leftResource, rightResource, originResource)).build();
 
-		MergeAllNonConflictingRunnable runnable = new MergeAllNonConflictingRunnable(isLeftEditable,
+		MergeNonConflictingRunnable runnable = new MergeNonConflictingRunnable(isLeftEditable,
 				isRightEditable, mergeMode);
 
 		MergeAllNonConflictingCommand command = new MergeAllNonConflictingCommand(changeRecorder, notifiers,
@@ -174,7 +181,7 @@
 		command.execute();
 
 		EList<Diff> differencesAfter = comparison.getDifferences();
-		// Test state of differences before command
+		// Test state of differences after command
 		// 0 Left Delete differences merged
 		leftDelete = filter(differencesAfter, and(fromSide(DifferenceSource.LEFT),
 				ofKind(DifferenceKind.DELETE), hasState(DifferenceState.MERGED)));
@@ -197,28 +204,24 @@
 	}
 
 	@Test
-	public void testAcceptAllNonConflictingChanges() throws IOException {
+	public void testAcceptAllNonConflictingChangesThreeWayWithoutConflicts() throws IOException {
 		MergeMode mergeMode = MergeMode.ACCEPT;
 		boolean leftToRight = false;
 		boolean isLeftEditable = true;
 		boolean isRightEditable = false;
 
-		Resource left = input.getLeftScope();
-		Resource right = input.getRightScope();
-		Resource origin = input.getOriginScope();
-
-		IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+		IComparisonScope scope = new DefaultComparisonScope(leftResource, rightResource, originResource);
 		Comparison comparison = EMFCompare.builder().build().compare(scope);
 
-		EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(left,
-				right, origin);
+		EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(
+				leftResource, rightResource, originResource);
 		ChangeRecorder changeRecorder = editingDomain.getChangeRecorder();
 
 		ImmutableSet.Builder<Notifier> notifiersBuilder = ImmutableSet.builder();
 		ImmutableSet<Notifier> notifiers = notifiersBuilder.add(comparison).addAll(
-				ImmutableList.of(left, right, origin)).build();
+				ImmutableList.of(leftResource, rightResource, originResource)).build();
 
-		MergeAllNonConflictingRunnable runnable = new MergeAllNonConflictingRunnable(isLeftEditable,
+		MergeNonConflictingRunnable runnable = new MergeNonConflictingRunnable(isLeftEditable,
 				isRightEditable, mergeMode);
 
 		MergeAllNonConflictingCommand command = new MergeAllNonConflictingCommand(changeRecorder, notifiers,
@@ -247,7 +250,7 @@
 		command.execute();
 
 		EList<Diff> differencesAfter = comparison.getDifferences();
-		// Test state of differences before command
+		// Test state of differences after command
 		// 3 Left Delete differences merged
 		leftDelete = filter(differencesAfter, and(fromSide(DifferenceSource.LEFT),
 				ofKind(DifferenceKind.DELETE), hasState(DifferenceState.MERGED)));
@@ -270,28 +273,24 @@
 	}
 
 	@Test
-	public void testRejectAllNonConflictingChanges() throws IOException {
+	public void testRejectAllNonConflictingChangesThreeWayWithoutConflicts() throws IOException {
 		MergeMode mergeMode = MergeMode.REJECT;
 		boolean leftToRight = false;
 		boolean isLeftEditable = true;
 		boolean isRightEditable = false;
 
-		Resource left = input.getLeftScope();
-		Resource right = input.getRightScope();
-		Resource origin = input.getOriginScope();
-
-		IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
+		IComparisonScope scope = new DefaultComparisonScope(leftResource, rightResource, originResource);
 		Comparison comparison = EMFCompare.builder().build().compare(scope);
 
-		EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(left,
-				right, origin);
+		EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(
+				leftResource, rightResource, originResource);
 		ChangeRecorder changeRecorder = editingDomain.getChangeRecorder();
 
 		ImmutableSet.Builder<Notifier> notifiersBuilder = ImmutableSet.builder();
 		ImmutableSet<Notifier> notifiers = notifiersBuilder.add(comparison).addAll(
-				ImmutableList.of(left, right, origin)).build();
+				ImmutableList.of(leftResource, rightResource, originResource)).build();
 
-		MergeAllNonConflictingRunnable runnable = new MergeAllNonConflictingRunnable(isLeftEditable,
+		MergeNonConflictingRunnable runnable = new MergeNonConflictingRunnable(isLeftEditable,
 				isRightEditable, mergeMode);
 
 		MergeAllNonConflictingCommand command = new MergeAllNonConflictingCommand(changeRecorder, notifiers,
@@ -320,7 +319,7 @@
 		command.execute();
 
 		EList<Diff> differencesAfter = comparison.getDifferences();
-		// Test state of differences before command
+		// Test state of differences after command
 		// 3 Left Delete differences merged
 		leftDelete = filter(differencesAfter, and(fromSide(DifferenceSource.LEFT),
 				ofKind(DifferenceKind.DELETE), hasState(DifferenceState.MERGED)));
@@ -341,4 +340,65 @@
 		command.dispose();
 		editingDomain.dispose();
 	}
+
+	@Test
+	public void testMergeAllNonConflictingChangesFromLeftToRightTwoWay() throws IOException {
+		testMergeAllNonConflictingTwoWay(MergeMode.LEFT_TO_RIGHT);
+	}
+
+	@Test
+	public void testMergeAllNonConflictingChangesFromRightToLeftTwoWay() throws IOException {
+		testMergeAllNonConflictingTwoWay(MergeMode.RIGHT_TO_LEFT);
+	}
+
+	private void testMergeAllNonConflictingTwoWay(MergeMode mergeMode) {
+		boolean isLeftEditable = true;
+		boolean isRightEditable = true;
+
+		IComparisonScope scope = new DefaultComparisonScope(leftResource, originResource, null);
+		Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+		EMFCompareEditingDomain editingDomain = (EMFCompareEditingDomain)EMFCompareEditingDomain.create(
+				leftResource, originResource, null);
+		ChangeRecorder changeRecorder = editingDomain.getChangeRecorder();
+
+		ImmutableSet.Builder<Notifier> notifiersBuilder = ImmutableSet.builder();
+		ImmutableSet<Notifier> notifiers = notifiersBuilder.add(comparison).addAll(
+				ImmutableList.of(leftResource, originResource)).build();
+
+		MergeNonConflictingRunnable runnable = new MergeNonConflictingRunnable(isLeftEditable,
+				isRightEditable, mergeMode);
+
+		MergeAllNonConflictingCommand command = new MergeAllNonConflictingCommand(changeRecorder, notifiers,
+				comparison, mergeMode.isLeftToRight(isLeftEditable, isRightEditable), mergerRegistry,
+				runnable);
+
+		EList<Diff> differencesBefore = comparison.getDifferences();
+		// Test state of differences before command
+		// 3 Left Delete differences
+		Iterable<Diff> leftDelete = filter(differencesBefore, and(fromSide(DifferenceSource.LEFT),
+				ofKind(DifferenceKind.DELETE), hasState(DifferenceState.UNRESOLVED)));
+		assertEquals(3, size(leftDelete));
+		// 3 Left Add differences
+		Iterable<Diff> leftAdd = filter(differencesBefore, and(fromSide(DifferenceSource.LEFT),
+				ofKind(DifferenceKind.ADD), hasState(DifferenceState.UNRESOLVED)));
+		assertEquals(3, size(leftAdd));
+
+		// Execute command
+		command.execute();
+
+		EList<Diff> differencesAfter = comparison.getDifferences();
+		// Test state of differences after command
+		// 3 Left Delete differences merged
+		leftDelete = filter(differencesAfter, and(fromSide(DifferenceSource.LEFT),
+				ofKind(DifferenceKind.DELETE), hasState(DifferenceState.MERGED)));
+		assertEquals(3, size(leftDelete));
+		// 3 Left Add differences merged
+		leftAdd = filter(differencesAfter, and(fromSide(DifferenceSource.LEFT), ofKind(DifferenceKind.ADD),
+				hasState(DifferenceState.MERGED)));
+		assertEquals(3, size(leftAdd));
+
+		command.dispose();
+		editingDomain.dispose();
+	}
 }
diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeAllNonConflictingRunnableTest.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeAllNonConflictingRunnableTest.java
deleted file mode 100644
index 4531852..0000000
--- a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeAllNonConflictingRunnableTest.java
+++ /dev/null
@@ -1,427 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 EclipseSource Muenchen 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:
- *     Philip Langer - initial API and implementation
- *******************************************************************************/
-package org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions;
-
-import static org.eclipse.emf.compare.DifferenceKind.ADD;
-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 static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.Collection;
-
-import org.eclipse.emf.common.util.BasicEList;
-import org.eclipse.emf.common.util.EList;
-import org.eclipse.emf.common.util.Monitor;
-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.DifferenceKind;
-import org.eclipse.emf.compare.DifferenceSource;
-import org.eclipse.emf.compare.DifferenceState;
-import org.eclipse.emf.compare.ReferenceChange;
-import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeAllNonConflictingRunnable;
-import org.eclipse.emf.compare.internal.merge.MergeMode;
-import org.eclipse.emf.compare.merge.IMerger;
-import org.eclipse.emf.compare.merge.IMerger.Registry;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Tests the {@link MergeAllNonConflictingRunnable} according to the specification given in <a
- * href="https://wiki.eclipse.org/EMF_Compare/Specifications/AllNonConflictingActions">the wiki</a>.
- * <p>
- * The goal of this test is to have a more unit-level test of the {@link MergeAllNonConflictingRunnable} (as
- * opposed to o.e.e.compare.ide.ui.tests.command.MergeAllCommandTests, which is more an integration test), as
- * well as to have a test in preparation of the refactorings panned for fixing bug 462884.
- * </p>
- * 
- * @author Philip Langer <planger@eclipsesource.com>
- */
-@SuppressWarnings("restriction")
-public class MergeAllNonConflictingRunnableTest {
-
-	private Comparison comparison;
-
-	private Registry mergerRegistry;
-
-	private IMerger merger;
-
-	private Diff leftDelete;
-
-	private Diff leftAdd;
-
-	private Diff rightDelete;
-
-	private Diff rightAdd;
-
-	@Before
-	public void setupMocks() {
-		comparison = mock(Comparison.class);
-		mergerRegistry = mock(Registry.class);
-		merger = mock(IMerger.class);
-		when(mergerRegistry.getHighestRankingMerger(any(Diff.class))).thenReturn(merger);
-	}
-
-	@Test
-	public void testMergeAllLeftToRightWithConflicts() {
-		final boolean isLeftToRight = true;
-		final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
-
-		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
-		addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
-
-		final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
-		sut.merge(comparison, isLeftToRight, mergerRegistry);
-
-		verifyHasBeenMergedLeftToRightOnly(leftAdd);
-		verifyHasNotBeenMerged(leftDelete, rightDelete, rightAdd);
-		verifyStateIsUnchanged(leftDelete, rightDelete, rightAdd);
-	}
-
-	@Test
-	public void testMergeAllLeftToRightWithoutConflicts() {
-		final boolean isLeftToRight = true;
-		final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
-
-		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
-		setNoConflictsInMockComparison();
-
-		final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
-		sut.merge(comparison, isLeftToRight, mergerRegistry);
-
-		verifyHasBeenMergedLeftToRightOnly(leftDelete, leftAdd);
-		verifyHasNotBeenMerged(rightDelete, rightAdd);
-		verifyStateIsUnchanged(rightDelete, rightAdd);
-	}
-
-	@Test
-	public void testMergeAllRightToLeftWithConflicts() {
-		final boolean isLeftToRight = false;
-		final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
-
-		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
-		addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
-
-		final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
-		sut.merge(comparison, isLeftToRight, mergerRegistry);
-
-		verifyHasBeenMergedRightToLeftOnly(rightAdd);
-		verifyHasNotBeenMerged(rightDelete, leftDelete, leftAdd);
-		verifyStateIsUnchanged(rightDelete, leftDelete, leftAdd);
-	}
-
-	@Test
-	public void testMergeAllRightToLeftWithoutConflicts() {
-		final boolean isLeftToRight = false;
-		final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
-
-		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
-		setNoConflictsInMockComparison();
-
-		final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
-		sut.merge(comparison, isLeftToRight, mergerRegistry);
-
-		verifyHasBeenMergedRightToLeftOnly(rightDelete, rightAdd);
-		verifyHasNotBeenMerged(leftDelete, leftAdd);
-		verifyStateIsUnchanged(leftDelete, leftAdd);
-	}
-
-	@Test
-	public void testAcceptAllWithoutConflicts() {
-		final boolean isLeftToRight = false;
-		final MergeMode mergeMode = MergeMode.ACCEPT;
-
-		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
-		setNoConflictsInMockComparison();
-
-		final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
-		sut.merge(comparison, isLeftToRight, mergerRegistry);
-
-		verifyHasBeenMergedRightToLeftOnly(rightDelete, rightAdd);
-		verifyHasNotBeenMerged(leftDelete, leftAdd);
-		verifyHasBeenMarkedAsMerged(leftAdd, leftDelete);
-	}
-
-	@Test
-	public void testRejectAllWithoutConflicts() {
-		final boolean isLeftToRight = false;
-		final MergeMode mergeMode = MergeMode.REJECT;
-
-		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
-		setNoConflictsInMockComparison();
-
-		final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
-		sut.merge(comparison, isLeftToRight, mergerRegistry);
-
-		verifyHasBeenMergedRightToLeftOnly(leftDelete, leftAdd);
-		verifyHasNotBeenMerged(rightDelete, rightAdd);
-		verifyHasBeenMarkedAsMerged(rightAdd, rightDelete);
-	}
-
-	@Test
-	public void testAcceptAllWithConflicts() {
-		final boolean isLeftToRight = false;
-		final MergeMode mergeMode = MergeMode.ACCEPT;
-
-		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
-		addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
-
-		final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
-		sut.merge(comparison, isLeftToRight, mergerRegistry);
-
-		verifyHasBeenMergedRightToLeftOnly(rightAdd);
-		verifyHasNotBeenMerged(leftDelete, rightDelete, leftAdd);
-		verifyHasBeenMarkedAsMerged(leftAdd);
-		verifyStateIsUnchanged(leftDelete, rightDelete);
-	}
-
-	@Test
-	public void testRejectAllWithConflicts() {
-		final boolean isLeftToRight = false;
-		final MergeMode mergeMode = MergeMode.REJECT;
-
-		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
-		addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
-
-		final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
-		sut.merge(comparison, isLeftToRight, mergerRegistry);
-
-		verifyHasBeenMergedRightToLeftOnly(leftAdd);
-		verifyHasNotBeenMerged(rightDelete, leftDelete, rightAdd);
-		verifyHasBeenMarkedAsMerged(rightAdd);
-		verifyStateIsUnchanged(leftDelete, rightDelete);
-	}
-
-	@Test
-	public void testTwoWayMergeAllLeftToRight() {
-		final boolean isLeftToRight = true;
-		final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
-
-		setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
-
-		final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
-		sut.merge(comparison, isLeftToRight, mergerRegistry);
-
-		verifyHasBeenMergedLeftToRightOnly(leftDelete, leftAdd);
-	}
-
-	@Test
-	public void testTwoWayMergeAllRightToLeft() {
-		final boolean isLeftToRight = false;
-		final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
-
-		setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
-
-		final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
-		sut.merge(comparison, isLeftToRight, mergerRegistry);
-
-		verifyHasBeenMergedRightToLeftOnly(leftDelete, leftAdd);
-	}
-
-	@Test
-	public void testTwoWayAcceptAll() {
-		final boolean isLeftToRight = false;
-		final MergeMode mergeMode = MergeMode.ACCEPT;
-
-		setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
-
-		final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
-		sut.merge(comparison, isLeftToRight, mergerRegistry);
-
-		verifyHasNotBeenMerged(leftDelete, leftAdd);
-		verifyHasBeenMarkedAsMerged(leftDelete, leftAdd);
-	}
-
-	@Test
-	public void testTwoWayRejectAll() {
-		final boolean isLeftToRight = false;
-		final MergeMode mergeMode = MergeMode.REJECT;
-
-		setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
-
-		final MergeAllNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
-		sut.merge(comparison, isLeftToRight, mergerRegistry);
-
-		verifyHasBeenMergedRightToLeftOnly(leftDelete, leftAdd);
-	}
-
-	private void addConflictsToMockComparison(Conflict... conflicts) {
-		when(comparison.getConflicts()).thenReturn(newEList(conflicts));
-	}
-
-	private void addDifferencesToMockComparison(Diff... diffs) {
-		when(comparison.getDifferences()).thenReturn(newEList(diffs));
-	}
-
-	private ReferenceChange mockReferenceChange(DifferenceSource side, DifferenceKind kind) {
-		final ReferenceChange diff = mock(ReferenceChange.class);
-		when(diff.getSource()).thenReturn(side);
-		when(diff.getKind()).thenReturn(kind);
-		when(diff.getState()).thenReturn(UNRESOLVED);
-		return diff;
-	}
-
-	private Conflict newConflict(Diff... diffs) {
-		Conflict conflict = mock(Conflict.class);
-		when(conflict.getKind()).thenReturn(ConflictKind.REAL);
-		when(conflict.getDifferences()).thenReturn(newEList(diffs));
-		for (Diff diff : diffs) {
-			when(diff.getConflict()).thenReturn(conflict);
-		}
-		return conflict;
-	}
-
-	private EList<Conflict> newEList(Conflict... diffs) {
-		final EList<Conflict> list = new BasicEList<Conflict>();
-		for (Conflict diff : diffs) {
-			list.add(diff);
-		}
-		return list;
-	}
-
-	private EList<Diff> newEList(Diff... diffs) {
-		final EList<Diff> list = new BasicEList<Diff>();
-		for (Diff diff : diffs) {
-			list.add(diff);
-		}
-		return list;
-	}
-
-	private void setNoConflictsInMockComparison() {
-		addConflictsToMockComparison(new Conflict[0]);
-	}
-
-	private void setThreeWayComparison() {
-		when(comparison.isThreeWay()).thenReturn(true);
-	}
-
-	private void setTwoWayComparison() {
-		when(comparison.isThreeWay()).thenReturn(false);
-	}
-
-	private void setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide() {
-		leftDelete = mockReferenceChange(LEFT, DELETE);
-		leftAdd = mockReferenceChange(LEFT, ADD);
-		rightDelete = mockReferenceChange(RIGHT, DELETE);
-		rightAdd = mockReferenceChange(RIGHT, ADD);
-
-		addDifferencesToMockComparison(leftDelete, leftAdd, rightDelete, rightAdd);
-		setThreeWayComparison();
-	}
-
-	private void setUpTwoWayComparisonWithOneAdditionAndOneDeletion() {
-		leftDelete = mockReferenceChange(LEFT, DELETE);
-		leftAdd = mockReferenceChange(LEFT, ADD);
-
-		addDifferencesToMockComparison(leftDelete, leftAdd);
-		setNoConflictsInMockComparison();
-		setTwoWayComparison();
-	}
-
-	private void verifyHasBeenMarkedAsMerged(Diff... diffs) {
-		for (Diff diff : diffs) {
-			verifyHasBeenMarkedAsMerged(diff);
-		}
-	}
-
-	private void verifyHasBeenMarkedAsMerged(Diff diff) {
-		verify(diff).setState(eq(MERGED));
-	}
-
-	private void verifyHasBeenMergedLeftToRightOnly(Diff diff) {
-		verify(merger, atLeastOnce()).copyLeftToRight(same(diff), any(Monitor.class));
-		verify(merger, never()).copyRightToLeft(same(diff), any(Monitor.class));
-	}
-
-	private void verifyHasBeenMergedLeftToRightOnly(Diff... diffs) {
-		for (Diff diff : diffs) {
-			verifyHasBeenMergedLeftToRightOnly(diff);
-		}
-	}
-
-	private void verifyHasBeenMergedRightToLeftOnly(Diff... diffs) {
-		for (Diff diff : diffs) {
-			verifyHasBeenMergedRightToLeftOnly(diff);
-		}
-	}
-
-	private void verifyHasBeenMergedRightToLeftOnly(Diff diff) {
-		verify(merger, atLeastOnce()).copyRightToLeft(same(diff), any(Monitor.class));
-		verify(merger, never()).copyLeftToRight(same(diff), any(Monitor.class));
-	}
-
-	private void verifyHasNotBeenMerged(Diff diff) {
-		verify(merger, never()).copyLeftToRight(same(diff), any(Monitor.class));
-		verify(merger, never()).copyRightToLeft(same(diff), any(Monitor.class));
-	}
-
-	private void verifyHasNotBeenMerged(Diff... diffs) {
-		for (Diff diff : diffs) {
-			verifyHasNotBeenMerged(diff);
-		}
-	}
-
-	private void verifyStateIsUnchanged(Diff diff) {
-		verify(diff, never()).setState(any(DifferenceState.class));
-	}
-
-	private void verifyStateIsUnchanged(Diff... diffs) {
-		for (Diff diff : diffs) {
-			verifyStateIsUnchanged(diff);
-		}
-	}
-
-	private MergeAllNonConflictingRunnable newMergeAllNonConflictingRunnable(MergeMode mergeMode) {
-		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();
-		}
-		return new MergeAllNonConflictingRunnable(isLeftEditable, isRightEditable, mergeMode) {
-			@Override
-			protected void addOrUpdateMergeData(Collection<Diff> differences, MergeMode mode) {
-				// do nothing to prevent call of EcoreUtil.getAdapter()
-			}
-
-			@Override
-			protected void markAsMerged(Diff diff, MergeMode mode, boolean mergeRightToLeft, Registry registry) {
-				// overwritten to prevent call of EcoreUtil.getAdapter()
-				// note that we rely on setting diff state to merged in verifyHasBeenMarkedAsMerged(Diff)
-				diff.setState(MERGED);
-			}
-		};
-	}
-
-}
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
new file mode 100644
index 0000000..d0ad712
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MergeNonConflictingRunnableTest.java
@@ -0,0 +1,637 @@
+/*******************************************************************************
+ * Copyright (c) 2015 EclipseSource Muenchen 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:
+ *     Philip Langer - 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.DifferenceKind.ADD;
+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 static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.same;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Collection;
+
+import org.eclipse.emf.common.util.BasicEList;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.Monitor;
+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.DifferenceKind;
+import org.eclipse.emf.compare.DifferenceSource;
+import org.eclipse.emf.compare.DifferenceState;
+import org.eclipse.emf.compare.Match;
+import org.eclipse.emf.compare.ReferenceChange;
+import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeNonConflictingRunnable;
+import org.eclipse.emf.compare.internal.merge.MergeMode;
+import org.eclipse.emf.compare.merge.IMerger;
+import org.eclipse.emf.compare.merge.IMerger.Registry;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests the {@link MergeNonConflictingRunnable} according to the specification given in <a
+ * href="https://wiki.eclipse.org/EMF_Compare/Specifications/AllNonConflictingActions">the wiki</a> and
+ * according to its capabilities to only merge a given collection of differences.
+ * <p>
+ * The goal of this test is to have a more unit-level test of the {@link MergeNonConflictingRunnable} (as
+ * opposed to o.e.e.compare.ide.ui.tests.command.MergeAllCommandTests, which is more an integration test).
+ * </p>
+ * 
+ * @author Philip Langer <planger@eclipsesource.com>
+ */
+@SuppressWarnings({"restriction", "nls" })
+public class MergeNonConflictingRunnableTest {
+
+	private Comparison comparison;
+
+	private Registry mergerRegistry;
+
+	private IMerger merger;
+
+	private Diff leftDelete;
+
+	private Diff leftAdd;
+
+	private Diff rightDelete;
+
+	private Diff rightAdd;
+
+	@Before
+	public void setupMocks() {
+		comparison = mock(Comparison.class);
+		mergerRegistry = mock(Registry.class);
+		merger = mock(IMerger.class);
+		when(mergerRegistry.getHighestRankingMerger(any(Diff.class))).thenReturn(merger);
+	}
+
+	@Test
+	public void testMergeAllLeftToRightWithConflicts() {
+		final boolean isLeftToRight = true;
+		final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedLeftToRightOnly(leftAdd);
+		verifyHasNotBeenMerged(leftDelete, rightDelete, rightAdd);
+		verifyStateIsUnchanged(leftDelete, rightDelete, rightAdd);
+	}
+
+	@Test
+	public void testMergeLeftToRightWithConflicts() {
+		final boolean isLeftToRight = true;
+		final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		// leftAdd is in the list and the only non-conflicting
+		sut.merge(asList(leftDelete, rightDelete, leftAdd), isLeftToRight, mergerRegistry);
+
+		// so it should be the only diff that has been merged
+		verifyHasBeenMergedLeftToRightOnly(leftAdd);
+		verifyHasNotBeenMerged(leftDelete, rightDelete, rightAdd);
+		verifyStateIsUnchanged(leftDelete, rightDelete, rightAdd);
+	}
+
+	@Test
+	public void testMergeLeftToRightWithConflictsAndLimitedSetOfDifferences() {
+		final boolean isLeftToRight = true;
+		final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		// leftAdd is not in the list, but the only non-conflicting on the left
+		sut.merge(asList(leftDelete, rightDelete), isLeftToRight, mergerRegistry);
+
+		// so no merge should be performed
+		verifyHasNotBeenMerged(leftAdd, leftDelete, rightDelete, rightAdd);
+		verifyStateIsUnchanged(leftAdd, leftDelete, rightDelete, rightAdd);
+	}
+
+	@Test
+	public void testMergeAllLeftToRightWithoutConflicts() {
+		final boolean isLeftToRight = true;
+		final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		setNoConflictsInMockComparison();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedLeftToRightOnly(leftDelete, leftAdd);
+		verifyHasNotBeenMerged(rightDelete, rightAdd);
+		verifyStateIsUnchanged(rightDelete, rightAdd);
+	}
+
+	@Test
+	public void testMergeLeftToRightWithoutConflicts() {
+		final boolean isLeftToRight = true;
+		final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		setNoConflictsInMockComparison();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		// leftDelete is in the list, but we do not include leftAdd
+		sut.merge(asList(leftDelete, rightDelete), isLeftToRight, mergerRegistry);
+
+		// so only leftDelete should be merged
+		verifyHasBeenMergedLeftToRightOnly(leftDelete);
+		verifyHasNotBeenMerged(leftAdd, rightDelete, rightAdd);
+		verifyStateIsUnchanged(leftAdd, rightDelete, rightAdd);
+	}
+
+	@Test
+	public void testMergeAllRightToLeftWithConflicts() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedRightToLeftOnly(rightAdd);
+		verifyHasNotBeenMerged(rightDelete, leftDelete, leftAdd);
+		verifyStateIsUnchanged(rightDelete, leftDelete, leftAdd);
+	}
+
+	@Test
+	public void testMergeRightToLeftWithConflicts() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		// rightAdd is in the list and the only non-conflicting on the right
+		sut.merge(asList(leftDelete, rightDelete, rightAdd), isLeftToRight, mergerRegistry);
+
+		// so it should be the only diff that has been merged
+		verifyHasBeenMergedRightToLeftOnly(rightAdd);
+		verifyHasNotBeenMerged(leftDelete, rightDelete, leftAdd);
+		verifyStateIsUnchanged(leftDelete, rightDelete, leftAdd);
+	}
+
+	@Test
+	public void testMergeRightToLeftWithConflictsAndLimitedSetOfDifferences() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		// rightAdd is not in the list, but the only non-conflicting
+		sut.merge(asList(leftDelete, rightDelete), isLeftToRight, mergerRegistry);
+
+		// so no merge should be performed
+		verifyHasNotBeenMerged(leftAdd, leftDelete, rightDelete, rightAdd);
+		verifyStateIsUnchanged(leftAdd, leftDelete, rightDelete, rightAdd);
+	}
+
+	@Test
+	public void testMergeAllRightToLeftWithoutConflicts() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		setNoConflictsInMockComparison();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedRightToLeftOnly(rightDelete, rightAdd);
+		verifyHasNotBeenMerged(leftDelete, leftAdd);
+		verifyStateIsUnchanged(leftDelete, leftAdd);
+	}
+
+	@Test
+	public void testMergeRightToLeftWithoutConflicts() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		setNoConflictsInMockComparison();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		// we do not include rightAdd, so it should not be merged
+		// and leftDelete should not be merged, because we merge left to right
+		sut.merge(asList(leftDelete, rightDelete), isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedRightToLeftOnly(rightDelete);
+		verifyHasNotBeenMerged(leftAdd, leftDelete, rightAdd);
+		verifyStateIsUnchanged(leftAdd, leftDelete, rightAdd);
+	}
+
+	@Test
+	public void testAcceptAllWithoutConflicts() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.ACCEPT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		setNoConflictsInMockComparison();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedRightToLeftOnly(rightDelete, rightAdd);
+		verifyHasNotBeenMerged(leftDelete, leftAdd);
+		verifyHasBeenMarkedAsMerged(leftAdd, leftDelete);
+	}
+
+	@Test
+	public void testAcceptWithoutConflicts() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.ACCEPT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		setNoConflictsInMockComparison();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		// rightDelete is in the list, but we do not include rightAdd
+		sut.merge(asList(leftAdd, leftDelete, rightDelete), isLeftToRight, mergerRegistry);
+
+		// so only rightDelete should be merged
+		verifyHasBeenMergedRightToLeftOnly(rightDelete);
+		verifyHasNotBeenMerged(leftDelete, leftAdd);
+		verifyHasBeenMarkedAsMerged(leftAdd, leftDelete);
+		verifyStateIsUnchanged(rightAdd);
+	}
+
+	@Test
+	public void testRejectAllWithoutConflicts() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.REJECT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		setNoConflictsInMockComparison();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedRightToLeftOnly(leftDelete, leftAdd);
+		verifyHasNotBeenMerged(rightDelete, rightAdd);
+		verifyHasBeenMarkedAsMerged(rightAdd, rightDelete);
+	}
+
+	@Test
+	public void testRejectWithoutConflicts() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.REJECT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		setNoConflictsInMockComparison();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		// leftDelete is in the list, but we do not include leftAdd
+		sut.merge(asList(leftDelete, rightDelete, rightAdd), isLeftToRight, mergerRegistry);
+
+		// so only leftDelete should be merged
+		verifyHasBeenMergedRightToLeftOnly(leftDelete);
+		verifyHasNotBeenMerged(rightDelete, rightAdd);
+		verifyHasBeenMarkedAsMerged(rightAdd, rightDelete);
+		verifyStateIsUnchanged(leftAdd);
+	}
+
+	@Test
+	public void testAcceptAllWithConflicts() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.ACCEPT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedRightToLeftOnly(rightAdd);
+		verifyHasNotBeenMerged(leftDelete, rightDelete, leftAdd);
+		verifyHasBeenMarkedAsMerged(leftAdd);
+		verifyStateIsUnchanged(leftDelete, rightDelete);
+	}
+
+	@Test
+	public void testRejectAllWithConflicts() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.REJECT;
+
+		setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide();
+		addConflictsToMockComparison(newConflict(leftDelete, rightDelete));
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedRightToLeftOnly(leftAdd);
+		verifyHasNotBeenMerged(rightDelete, leftDelete, rightAdd);
+		verifyHasBeenMarkedAsMerged(rightAdd);
+		verifyStateIsUnchanged(leftDelete, rightDelete);
+	}
+
+	@Test
+	public void testTwoWayMergeAllLeftToRight() {
+		final boolean isLeftToRight = true;
+		final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
+
+		setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedLeftToRightOnly(leftDelete, leftAdd);
+	}
+
+	@Test
+	public void testTwoWayMergeLeftToRight() {
+		final boolean isLeftToRight = true;
+		final MergeMode mergeMode = MergeMode.LEFT_TO_RIGHT;
+
+		setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(asList(leftDelete), isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedLeftToRightOnly(leftDelete);
+		verifyHasNotBeenMerged(leftAdd);
+		verifyStateIsUnchanged(leftAdd);
+	}
+
+	@Test
+	public void testTwoWayMergeAllRightToLeft() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
+
+		setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedRightToLeftOnly(leftDelete, leftAdd);
+	}
+
+	@Test
+	public void testTwoWayMergeRightToLeft() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.RIGHT_TO_LEFT;
+
+		setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(asList(leftDelete), isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedRightToLeftOnly(leftDelete);
+		verifyHasNotBeenMerged(leftAdd);
+		verifyStateIsUnchanged(leftAdd);
+	}
+
+	@Test
+	public void testTwoWayAcceptAll() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.ACCEPT;
+
+		setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+		verifyHasNotBeenMerged(leftDelete, leftAdd);
+		verifyHasBeenMarkedAsMerged(leftDelete, leftAdd);
+	}
+
+	@Test
+	public void testTwoWayAccept() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.ACCEPT;
+
+		setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(asList(leftDelete), isLeftToRight, mergerRegistry);
+
+		verifyHasNotBeenMerged(leftDelete);
+		verifyHasBeenMarkedAsMerged(leftDelete);
+		verifyStateIsUnchanged(leftAdd);
+	}
+
+	@Test
+	public void testTwoWayRejectAll() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.REJECT;
+
+		setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(comparison, isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedRightToLeftOnly(leftDelete, leftAdd);
+	}
+
+	@Test
+	public void testTwoWayReject() {
+		final boolean isLeftToRight = false;
+		final MergeMode mergeMode = MergeMode.REJECT;
+
+		setUpTwoWayComparisonWithOneAdditionAndOneDeletion();
+
+		final MergeNonConflictingRunnable sut = newMergeAllNonConflictingRunnable(mergeMode);
+		sut.merge(asList(leftAdd), isLeftToRight, mergerRegistry);
+
+		verifyHasBeenMergedRightToLeftOnly(leftAdd);
+		verifyHasNotBeenMerged(leftDelete);
+	}
+
+	private void addConflictsToMockComparison(Conflict... conflicts) {
+		when(comparison.getConflicts()).thenReturn(newEList(conflicts));
+	}
+
+	private void addDifferencesToMockComparison(Diff... diffs) {
+		when(comparison.getDifferences()).thenReturn(newEList(diffs));
+		for (Diff diff : diffs) {
+			final Match match = mock(Match.class);
+			when(match.getComparison()).thenReturn(comparison);
+			when(diff.getMatch()).thenReturn(match);
+		}
+	}
+
+	private ReferenceChange mockReferenceChange(DifferenceSource side, DifferenceKind kind, String name) {
+		final ReferenceChange diff = mock(ReferenceChange.class, name);
+		when(diff.getSource()).thenReturn(side);
+		when(diff.getKind()).thenReturn(kind);
+		when(diff.getState()).thenReturn(UNRESOLVED);
+		return diff;
+	}
+
+	private Conflict newConflict(Diff... diffs) {
+		Conflict conflict = mock(Conflict.class);
+		when(conflict.getKind()).thenReturn(ConflictKind.REAL);
+		when(conflict.getDifferences()).thenReturn(newEList(diffs));
+		for (Diff diff : diffs) {
+			when(diff.getConflict()).thenReturn(conflict);
+		}
+		return conflict;
+	}
+
+	private EList<Conflict> newEList(Conflict... diffs) {
+		final EList<Conflict> list = new BasicEList<Conflict>();
+		for (Conflict diff : diffs) {
+			list.add(diff);
+		}
+		return list;
+	}
+
+	private EList<Diff> newEList(Diff... diffs) {
+		final EList<Diff> list = new BasicEList<Diff>();
+		for (Diff diff : diffs) {
+			list.add(diff);
+		}
+		return list;
+	}
+
+	private void setNoConflictsInMockComparison() {
+		addConflictsToMockComparison(new Conflict[0]);
+	}
+
+	private void setThreeWayComparison() {
+		when(Boolean.valueOf(comparison.isThreeWay())).thenReturn(Boolean.TRUE);
+	}
+
+	private void setTwoWayComparison() {
+		when(Boolean.valueOf(comparison.isThreeWay())).thenReturn(Boolean.FALSE);
+	}
+
+	private void setUpThreeWayComparisonWithOneAdditionAndDeletionOnEachSide() {
+		leftDelete = mockReferenceChange(LEFT, DELETE, "leftDelete");
+		leftAdd = mockReferenceChange(LEFT, ADD, "leftAdd");
+		rightDelete = mockReferenceChange(RIGHT, DELETE, "rightDelete");
+		rightAdd = mockReferenceChange(RIGHT, ADD, "rightAdd");
+
+		addDifferencesToMockComparison(leftDelete, leftAdd, rightDelete, rightAdd);
+		setThreeWayComparison();
+	}
+
+	private void setUpTwoWayComparisonWithOneAdditionAndOneDeletion() {
+		leftDelete = mockReferenceChange(LEFT, DELETE, "leftDelete");
+		leftAdd = mockReferenceChange(LEFT, ADD, "leftAdd");
+
+		addDifferencesToMockComparison(leftDelete, leftAdd);
+		setNoConflictsInMockComparison();
+		setTwoWayComparison();
+	}
+
+	private void verifyHasBeenMarkedAsMerged(Diff... diffs) {
+		for (Diff diff : diffs) {
+			verifyHasBeenMarkedAsMerged(diff);
+		}
+	}
+
+	private void verifyHasBeenMarkedAsMerged(Diff diff) {
+		verify(diff).setState(eq(MERGED));
+	}
+
+	private void verifyHasBeenMergedLeftToRightOnly(Diff diff) {
+		verify(merger, atLeastOnce()).copyLeftToRight(same(diff), any(Monitor.class));
+		verify(merger, never()).copyRightToLeft(same(diff), any(Monitor.class));
+	}
+
+	private void verifyHasBeenMergedLeftToRightOnly(Diff... diffs) {
+		for (Diff diff : diffs) {
+			verifyHasBeenMergedLeftToRightOnly(diff);
+		}
+	}
+
+	private void verifyHasBeenMergedRightToLeftOnly(Diff... diffs) {
+		for (Diff diff : diffs) {
+			verifyHasBeenMergedRightToLeftOnly(diff);
+		}
+	}
+
+	private void verifyHasBeenMergedRightToLeftOnly(Diff diff) {
+		verify(merger, atLeastOnce()).copyRightToLeft(same(diff), any(Monitor.class));
+		verify(merger, never()).copyLeftToRight(same(diff), any(Monitor.class));
+	}
+
+	private void verifyHasNotBeenMerged(Diff diff) {
+		verify(merger, never()).copyLeftToRight(same(diff), any(Monitor.class));
+		verify(merger, never()).copyRightToLeft(same(diff), any(Monitor.class));
+	}
+
+	private void verifyHasNotBeenMerged(Diff... diffs) {
+		for (Diff diff : diffs) {
+			verifyHasNotBeenMerged(diff);
+		}
+	}
+
+	private void verifyStateIsUnchanged(Diff diff) {
+		verify(diff, never()).setState(any(DifferenceState.class));
+	}
+
+	private void verifyStateIsUnchanged(Diff... diffs) {
+		for (Diff diff : diffs) {
+			verifyStateIsUnchanged(diff);
+		}
+	}
+
+	private MergeNonConflictingRunnable newMergeAllNonConflictingRunnable(MergeMode mergeMode) {
+		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();
+		}
+		return new MergeNonConflictingRunnable(isLeftEditable, isRightEditable, mergeMode) {
+			@Override
+			protected void addOrUpdateMergeData(Collection<Diff> differences, MergeMode mode) {
+				// do nothing to prevent call of EcoreUtil.getAdapter()
+			}
+
+			@Override
+			protected void markAsMerged(Diff diff, MergeMode mode, boolean mergeRightToLeft, Registry registry) {
+				// overwritten to prevent call of EcoreUtil.getAdapter()
+				// note that we rely on setting diff state to merged in verifyHasBeenMarkedAsMerged(Diff)
+				diff.setState(MERGED);
+			}
+		};
+	}
+
+}
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 8552852..1944cb3 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
@@ -31,7 +31,7 @@
 import org.eclipse.emf.compare.ide.ui.tests.logical.resolver.ThreadedModelResolverWithCustomDependencyProviderTest;
 import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.NavigatableTest;
 import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions.MergeActionTest;
-import org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions.MergeAllNonConflictingRunnableTest;
+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.notloadedfragment.NotLoadedFragmentNodeTest;
 import org.eclipse.emf.compare.ide.ui.tests.unit.DependenciesTest;
@@ -52,7 +52,7 @@
 		ThreadedModelResolverWithCustomDependencyProviderTest.class, DependencyGraphUpdaterTest.class,
 		GraphResolutionTest.class, EMFModelProviderTest.class, MergeAllCommandTests.class,
 		LocalMonitoredProxyCreationListenerTest.class, RemoteMonitoredProxyCreationListenerTest.class,
-		MergeAllNonConflictingRunnableTest.class })
+		MergeNonConflictingRunnableTest.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/structuremergeviewer/actions/MergeAllNonConflictingAction.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingAction.java
index 8f4e6bf..46c0f85 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingAction.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013 Obeo.
+ * Copyright (c) 2013, 2015 Obeo.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -10,8 +10,6 @@
  *******************************************************************************/
 package org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions;
 
-import com.google.common.base.Preconditions;
-
 import java.util.Collections;
 import java.util.List;
 
@@ -52,21 +50,8 @@
 	public MergeAllNonConflictingAction(ICompareEditingDomain editingDomain, Comparison comparison,
 			IMerger.Registry mergerRegistry, MergeMode mode, boolean isLeftEditable, boolean isRightEditable) {
 		super(editingDomain, mergerRegistry, mode, isLeftEditable, isRightEditable, null);
-
-		Preconditions.checkNotNull(mode);
-		Preconditions.checkState(isLeftEditable || isRightEditable);
-		// if left and right editable, the only accepted mode are LtR or RtL
-		if (isLeftEditable && isRightEditable) {
-			Preconditions.checkState(mode == MergeMode.LEFT_TO_RIGHT || mode == MergeMode.RIGHT_TO_LEFT);
-		}
-		// if mode is accept or reject, left and right can't be both read only (no action should be created in
-		// this case) and can't be both editable.
-		if (isLeftEditable != isRightEditable) {
-			Preconditions.checkState(mode == MergeMode.ACCEPT || mode == MergeMode.REJECT);
-		}
-
 		this.comparison = comparison;
-		this.runnable = new MergeAllNonConflictingRunnable(isLeftEditable, isRightEditable, mode);
+		this.runnable = new MergeNonConflictingRunnable(isLeftEditable, isRightEditable, mode);
 	}
 
 	@Override
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingRunnable.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeNonConflictingRunnable.java
similarity index 83%
rename from plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingRunnable.java
rename to plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeNonConflictingRunnable.java
index 123793b..bd55894 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingRunnable.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeNonConflictingRunnable.java
@@ -7,7 +7,7 @@
  * 
  * Contributors:
  *     Obeo - initial API and implementation
- *     Philip Langer - bug 469355
+ *     Philip Langer - bug 469355, bug 462884, refactorings
  *******************************************************************************/
 package org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions;
 
@@ -34,10 +34,12 @@
 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.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.internal.utils.Graph;
 import org.eclipse.emf.compare.internal.utils.PruningIterator;
 import org.eclipse.emf.compare.merge.BatchMerger;
@@ -47,11 +49,11 @@
 import org.eclipse.emf.compare.merge.IMerger2;
 
 /**
- * Implements the "merge all non-conflicting" action.
+ * Implements the "merge non-conflicting" and "merge all non-conflicting" action.
  * 
  * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
  */
-public class MergeAllNonConflictingRunnable extends AbstractMergeRunnable implements IMergeAllNonConflictingRunnable {
+public class MergeNonConflictingRunnable extends AbstractMergeRunnable implements IMergeAllNonConflictingRunnable, IMergeRunnable {
 	/**
 	 * Default constructor.
 	 * 
@@ -62,7 +64,7 @@
 	 * @param mergeMode
 	 *            Merge mode for this operation.
 	 */
-	public MergeAllNonConflictingRunnable(boolean isLeftEditable, boolean isRightEditable, MergeMode mergeMode) {
+	public MergeNonConflictingRunnable(boolean isLeftEditable, boolean isRightEditable, MergeMode mergeMode) {
 		super(isLeftEditable, isRightEditable, mergeMode);
 	}
 
@@ -71,20 +73,52 @@
 	 */
 	public Iterable<Diff> merge(Comparison comparison, boolean leftToRight, Registry mergerRegistry) {
 		checkState(getMergeMode().isLeftToRight(isLeftEditable(), isRightEditable()) == leftToRight);
+		return doMergeNonConflicting(comparison.getDifferences(), comparison, leftToRight, mergerRegistry);
+	}
 
+	/**
+	 * {@inheritDoc}
+	 * <p>
+	 * Differences that are conflicting or that depend on conflicting differences will be left out.
+	 * Non-conflicting differences that are implied or required by the given differences will be merged, also
+	 * if they are not explicitly included in the given list of {@code differences}.
+	 * </p>
+	 */
+	@SuppressWarnings("unchecked")
+	public void merge(List<? extends Diff> differences, boolean leftToRight, Registry mergerRegistry) {
+		checkState(getMergeMode().isLeftToRight(isLeftEditable(), isRightEditable()) == leftToRight);
+		checkState(!differences.isEmpty() && ComparisonUtil.getComparison(differences.get(0)) != null);
+		final Comparison comparison = ComparisonUtil.getComparison(differences.get(0));
+		doMergeNonConflicting((Collection<Diff>)differences, comparison, leftToRight, mergerRegistry);
+	}
+
+	/**
+	 * Performs the merge of the non-conflicting differences in the given {@code differences}.
+	 * 
+	 * @param differences
+	 *            The differences to be merged.
+	 * @param comparison
+	 *            The comparison containing the differences to decide on whether conflicts are in play or not
+	 *            and to determine whether this is a three- or two-way comparison.
+	 * @param leftToRight
+	 *            The direction in which {@code differences} should be merged.
+	 * @param mergerRegistry
+	 *            The registry of mergers.
+	 * @return an iterable over the differences that have actually been merged by this operation.
+	 */
+	private Iterable<Diff> doMergeNonConflicting(Collection<Diff> differences, Comparison comparison,
+			boolean leftToRight, Registry mergerRegistry) {
 		final Iterable<Diff> affectedChanges;
 		if (hasRealConflict(comparison)) {
 			// This is a 3-way comparison, pre-merge what can be.
-			affectedChanges = mergeWithConflicts(comparison.getDifferences(), leftToRight, mergerRegistry);
+			affectedChanges = mergeWithConflicts(differences, leftToRight, mergerRegistry);
 		} else if (comparison.isThreeWay()) {
 			// This is a 3-way comparison without conflicts
-			affectedChanges = mergeThreeWayWithoutConflicts(comparison.getDifferences(), leftToRight,
-					mergerRegistry);
+			affectedChanges = mergeThreeWayWithoutConflicts(differences, leftToRight, mergerRegistry);
 		} else {
 			// This is a 2-way comparison
-			affectedChanges = mergeTwoWay(comparison.getDifferences(), leftToRight, mergerRegistry);
+			affectedChanges = mergeTwoWay(differences, leftToRight, mergerRegistry);
 		}
-
 		return affectedChanges;
 	}