@Test void mergeWhenUserHasChangedAllContent() throws Exception { MergeResult<String> result; result = this.diffManager.merge(Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3", "Line 4 Added"), Arrays.asList("New content", "That is completely different"), null); assertEquals(1, result.getLog().getLogs(LogLevel.ERROR).size()); assertTrue(result.getLog().getLogs(LogLevel.ERROR).get(0).toString() .contains("Conflict between")); assertEquals(1, result.getConflicts().size()); Conflict<String> conflict = createConflict(0, Type.CHANGE, 0, 0, Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("New content", "That is completely different"), Type.CHANGE, 0, 0, Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3")); assertEquals(conflict, result.getConflicts().get(0)); assertEquals(Arrays.asList("New content", "That is completely different"), result.getMerged()); MergeConfiguration<String> mergeConfiguration = new MergeConfiguration<>(); mergeConfiguration.setFallbackOnConflict(MergeConfiguration.Version.PREVIOUS); result = this.diffManager.merge(Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3", "Line 4 Added"), Arrays.asList("New content", "That is completely different"), mergeConfiguration); assertEquals(1, result.getLog().getLogs(LogLevel.ERROR).size()); assertTrue(result.getLog().getLogs(LogLevel.ERROR).get(0).toString() .contains("Conflict between")); assertEquals(conflict, result.getConflicts().get(0)); assertEquals(Arrays.asList("Line 1", "Line 2", "Line 3"), result.getMerged()); mergeConfiguration.setFallbackOnConflict(MergeConfiguration.Version.NEXT); result = this.diffManager.merge(Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3", "Line 4 Added"), Arrays.asList("New content", "That is completely different"), mergeConfiguration); assertEquals(1, result.getLog().getLogs(LogLevel.ERROR).size()); assertTrue(result.getLog().getLogs(LogLevel.ERROR).get(0).toString() .contains("Conflict between")); assertEquals(conflict, result.getConflicts().get(0)); assertEquals(Arrays.asList("Line 1", "Line 2 modified", "Line 3", "Line 4 Added"), result.getMerged()); result = this.diffManager.merge(Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3", "Line 4 Added"), Collections.emptyList(), null); conflict = createConflict(0, Type.CHANGE, 0, 0, Arrays.asList("Line 1", "Line 2", "Line 3"), Collections.emptyList(), Type.CHANGE, 0, 0, Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3")); assertEquals(1, result.getLog().getLogs(LogLevel.ERROR).size()); assertTrue(result.getLog().getLogs(LogLevel.ERROR).get(0).toString() .contains("Conflict between")); assertEquals(conflict, result.getConflicts().get(0)); assertEquals(Collections.emptyList(), result.getMerged()); mergeConfiguration.setFallbackOnConflict(MergeConfiguration.Version.PREVIOUS); result = this.diffManager.merge(Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3", "Line 4 Added"), Collections.emptyList(), mergeConfiguration); assertEquals(1, result.getLog().getLogs(LogLevel.ERROR).size()); assertTrue(result.getLog().getLogs(LogLevel.ERROR).get(0).toString() .contains("Conflict between")); assertEquals(conflict, result.getConflicts().get(0)); assertEquals(Arrays.asList("Line 1", "Line 2", "Line 3"), result.getMerged()); mergeConfiguration.setFallbackOnConflict(MergeConfiguration.Version.NEXT); result = this.diffManager.merge(Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3", "Line 4 Added"), Collections.emptyList(), mergeConfiguration); assertEquals(1, result.getLog().getLogs(LogLevel.ERROR).size()); assertTrue(result.getLog().getLogs(LogLevel.ERROR).get(0).toString() .contains("Conflict between")); assertEquals(conflict, result.getConflicts().get(0)); assertEquals(Arrays.asList("Line 1", "Line 2 modified", "Line 3", "Line 4 Added"), result.getMerged()); result = this.diffManager.merge(Arrays.asList("Line 1", "Line 2", "Line 3"), Collections.emptyList(), Arrays.asList("Line 1", "Line 2 modified", "Line 3", "Line 4 Added"), null); conflict = createConflict(0, Type.CHANGE, 0, 0, Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3"), Type.CHANGE, 0, 0, Arrays.asList("Line 1", "Line 2", "Line 3"), Collections.emptyList()); assertEquals(1, result.getLog().getLogs(LogLevel.ERROR).size()); assertTrue(result.getLog().getLogs(LogLevel.ERROR).get(0).toString() .contains("Conflict between")); assertEquals(conflict, result.getConflicts().get(0)); assertEquals(Arrays.asList("Line 1", "Line 2 modified", "Line 3", "Line 4 Added"), result.getMerged()); mergeConfiguration.setFallbackOnConflict(MergeConfiguration.Version.PREVIOUS); result = this.diffManager.merge(Arrays.asList("Line 1", "Line 2", "Line 3"), Collections.emptyList(), Arrays.asList("Line 1", "Line 2 modified", "Line 3", "Line 4 Added"), mergeConfiguration); assertEquals(1, result.getLog().getLogs(LogLevel.ERROR).size()); assertTrue(result.getLog().getLogs(LogLevel.ERROR).get(0).toString() .contains("Conflict between")); assertEquals(conflict, result.getConflicts().get(0)); assertEquals(Arrays.asList("Line 1", "Line 2", "Line 3"), result.getMerged()); mergeConfiguration.setFallbackOnConflict(MergeConfiguration.Version.NEXT); result = this.diffManager.merge(Arrays.asList("Line 1", "Line 2", "Line 3"), Collections.emptyList(), Arrays.asList("Line 1", "Line 2 modified", "Line 3", "Line 4 Added"), mergeConfiguration); assertEquals(1, result.getLog().getLogs(LogLevel.ERROR).size()); assertTrue(result.getLog().getLogs(LogLevel.ERROR).get(0).toString() .contains("Conflict between")); assertEquals(conflict, result.getConflicts().get(0)); assertEquals(Collections.emptyList(), result.getMerged()); result = this.diffManager.merge(Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("New content", "That is completely different"), Arrays.asList("New content", "That is completely different"), null); assertEquals(0, result.getLog().getLogs(LogLevel.ERROR).size()); assertEquals(0, result.getConflicts().size()); assertEquals(Arrays.asList("New content", "That is completely different"), result.getMerged()); mergeConfiguration.setFallbackOnConflict(MergeConfiguration.Version.PREVIOUS); result = this.diffManager.merge(Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("New content", "That is completely different"), Arrays.asList("New content", "That is completely different"), mergeConfiguration); assertEquals(0, result.getLog().getLogs(LogLevel.ERROR).size()); assertEquals(0, result.getConflicts().size()); assertEquals(Arrays.asList("New content", "That is completely different"), result.getMerged()); mergeConfiguration = null; conflict = this.createConflict(2, Type.CHANGE, 2, 2, Arrays.asList("started to walk"), Arrays.asList("started to walk", "dressed in black"), Type.CHANGE, 2, 2, Arrays.asList("started to walk"), Arrays.asList("dressed in black")); result = this.diffManager .merge( Arrays.asList( "Once upon a time", "a wolf", "started to walk", "in the forest" ), Arrays.asList( "Once upon a time", "a wolf", "dressed in black", "in the forest" ), Arrays.asList( "Once upon a time", "a wolf", "started to walk", "dressed in black", "in the forest" ), mergeConfiguration); assertEquals(1, result.getLog().getLogs(LogLevel.ERROR).size()); assertEquals(1, result.getConflicts().size()); assertEquals(conflict, result.getConflicts().get(0)); assertEquals( Arrays.asList("Once upon a time", "a wolf", "started to walk", "dressed in black", "in the forest"), result.getMerged()); mergeConfiguration = null; conflict = createConflict(0, Type.CHANGE, 0, 0, Arrays.asList("A first edit from a tab."), Arrays.asList("A second edit from another tab.", "Another line"), Type.CHANGE, 0, 0, Arrays.asList("A first edit from a tab."), Arrays.asList("A second edit from another tab.")); result = this.diffManager.merge( Arrays.asList("A first edit from a tab."), Arrays.asList("A second edit from another tab."), Arrays.asList("A second edit from another tab.", "Another line"), mergeConfiguration); assertEquals(1, result.getLog().getLogs(LogLevel.ERROR).size()); assertEquals(1, result.getConflicts().size()); assertEquals(conflict, result.getConflicts().get(0)); assertEquals(Arrays.asList("A second edit from another tab.", "Another line"), result.getMerged()); conflict = this.createConflict(0, Type.CHANGE, 0, 0, Arrays.asList( "A fifth edit from another tab.", "Another line.", "Yet another line with other few changes." ), Arrays.asList( "A sixth edit from the first tab.", "Another line.", "Yet another line edited from the first tab." ), Type.CHANGE, 0, 0, Arrays.asList( "A fifth edit from another tab.", "Another line.", "Yet another line with other few changes." ), Arrays.asList( "A sixth edit from the second tab.", "Another line with small changes.", "Another edit from the second tab." )); result = this.diffManager.merge( Arrays.asList( "A fifth edit from another tab.", "Another line.", "Yet another line with other few changes." ), Arrays.asList( "A sixth edit from the second tab.", "Another line with small changes.", "Another edit from the second tab." ), Arrays.asList( "A sixth edit from the first tab.", "Another line.", "Yet another line edited from the first tab." ), mergeConfiguration); assertEquals(1, result.getConflicts().size()); assertEquals(conflict, result.getConflicts().get(0)); conflict = this.createConflict(0, Type.CHANGE, 0, 0, Arrays.asList( "A fifth edit from another tab.", "Another line.", "Yet another line with other few changes." ), Arrays.asList( "A sixth edit from the first tab.", "Another line.", "Yet another line edited from the first tab." ), Type.CHANGE, 0, 0, Arrays.asList( "A fifth edit from another tab.", "Another line.", "Yet another line with other few changes." ), Collections.emptyList()); result = this.diffManager.merge( Arrays.asList( "A fifth edit from another tab.", "Another line.", "Yet another line with other few changes." ), Collections.emptyList(), Arrays.asList( "A sixth edit from the first tab.", "Another line.", "Yet another line edited from the first tab." ), mergeConfiguration); assertEquals(1, result.getConflicts().size()); assertEquals(conflict, result.getConflicts().get(0)); conflict = this.createConflict(0, Type.CHANGE, 0, 0, Arrays.asList("Some content."), Arrays.asList("Another content", "On multiple lines."), Type.CHANGE, 0, 0, Arrays.asList("Some content."), Arrays.asList( "Some content.", "", "And now if I try", "to put something", "", "with empty lines", "like this" )); result = this.diffManager.merge( Arrays.asList( "Some content." ), Arrays.asList( "Some content.", "", "And now if I try", "to put something", "", "with empty lines", "like this" ), Arrays.asList( "Another content", "On multiple lines." ), mergeConfiguration); assertEquals(1, result.getConflicts().size()); assertEquals(conflict, result.getConflicts().get(0)); conflict = this.createConflict(1, Type.CHANGE, 1, 1, Arrays.asList("Second line.", "Third line."), Arrays.asList("Second line.", "Line N°4"), Type.CHANGE, 1, 1, Arrays.asList("Second line.", "Third line."), Arrays.asList("Line N°2", "Third line.")); Conflict<String> conflict2 = this.createConflict(5, Type.CHANGE, 5, 5, Collections.emptyList(), Arrays.asList("6th line."), Type.CHANGE, 5, 5, Collections.emptyList(), Arrays.asList("Sixth line.")); result = this.diffManager.merge( Arrays.asList( "First line.", "Second line.", "Third line.", "Fourth line.", "Fifth line.", "Seventh line." ), Arrays.asList( "First line.", "Line N°2", "Third line.", "Fifth line.", "Sixth line.", "Seventh line." ), Arrays.asList( "First line.", "Second line.", "Line N°4", "Fifth line.", "6th line.", "Seventh line." ), mergeConfiguration); assertEquals(2, result.getConflicts().size()); assertEquals(conflict, result.getConflicts().get(0)); assertEquals(conflict2, result.getConflicts().get(1)); assertEquals(Arrays.asList( "First line.", "Second line.", "Line N°4", "Fifth line.", "6th line.", "Seventh line." ), result.getMerged()); conflict = this.createConflict(0, Type.CHANGE, 0, 0, Arrays.asList("A second edit from another tab.", "A new line."), Arrays.asList("A fourth edit from second tab.", "Another line."), Type.CHANGE, 0, 0, Arrays.asList("A second edit from another tab.", "A new line."), Arrays.asList("A third edit from another tab.", "Another line.", "Yet another line.")); result = this.diffManager.merge( Arrays.asList("A second edit from another tab.", "A new line."), Arrays.asList("A third edit from another tab.", "Another line.", "Yet another line."), Arrays.asList("A fourth edit from second tab.", "Another line."), mergeConfiguration); assertEquals(1, result.getConflicts().size()); assertEquals(conflict, result.getConflicts().get(0)); mergeConfiguration = null; conflict = this.createConflict(1, Type.CHANGE, 1, 1, Arrays.asList("Anything else"), Arrays.asList("", "And now if I try", "to put something", "", "with empty lines", "like this"), Type.CHANGE, 1, 1, Arrays.asList("Anything else"), Arrays.asList("On multiple lines.")); result = diffManager.merge(Arrays.asList( "Some content.", "Anything else" ), Arrays.asList( "Some content.", "On multiple lines." ), Arrays.asList( "Some content.", "", "And now if I try", "to put something", "", "with empty lines", "like this" ), mergeConfiguration); assertEquals(1, result.getConflicts().size()); assertEquals(conflict, result.getConflicts().get(0)); }
@Override public <E> MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current, MergeConfiguration<E> configuration) throws MergeException { DefaultMergeResult<E> mergeResult = new DefaultMergeResult<>(commonAncestor, next, current); DiffResult<E> diffNextResult; try { diffNextResult = diff(commonAncestor, next, null); } catch (DiffException e) { throw new MergeException("Faile to diff between common ancestor and next version", e); } mergeResult.getLog().addAll(diffNextResult.getLog()); Patch<E> patchNext = diffNextResult.getPatch(); if (patchNext.isEmpty()) { return mergeResult; } if (current.isEmpty() && (commonAncestor.isEmpty() || next.isEmpty())) { if (commonAncestor.isEmpty()) { mergeResult.setMerged(next); } else if (next.isEmpty()) { mergeResult.getLog().warn("The modification was already applied"); } } else { DiffResult<E> diffCurrentResult; try { diffCurrentResult = diff(commonAncestor, current, null); } catch (DiffException e) { throw new MergeException("Fail to diff between common ancestor and current version", e); } mergeResult.getLog().addAll(diffCurrentResult.getLog()); Patch<E> patchCurrent = diffCurrentResult.getPatch(); mergeResult.setMerged(new ArrayList<>()); if (patchCurrent.isEmpty()) { mergeResult.setMerged(next); } else if (!current.equals(next) && (isFullyModified(commonAncestor, patchCurrent) || isFullyModified(commonAncestor, patchNext))) { Delta<E> deltaNext = nextElement(patchNext); Delta<E> deltaCurrent = nextElement(patchCurrent); List<ConflictDecision<E>> conflictDecisionList = (configuration != null) ? configuration.getConflictDecisionList() : Collections.emptyList(); int newIndex = applyDecision(conflictDecisionList, mergeResult.getMerged(), 0); if (newIndex == Integer.MIN_VALUE) { logConflict(mergeResult, deltaCurrent, deltaNext, commonAncestor, next, current, 0); mergeResult.setMerged(fallback(commonAncestor, next, current, configuration)); } } else { merge(mergeResult, commonAncestor, next, current, patchNext, patchCurrent, configuration); } } return mergeResult; }
DefaultDiffManager implements DiffManager { @Override public <E> MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current, MergeConfiguration<E> configuration) throws MergeException { DefaultMergeResult<E> mergeResult = new DefaultMergeResult<>(commonAncestor, next, current); DiffResult<E> diffNextResult; try { diffNextResult = diff(commonAncestor, next, null); } catch (DiffException e) { throw new MergeException("Faile to diff between common ancestor and next version", e); } mergeResult.getLog().addAll(diffNextResult.getLog()); Patch<E> patchNext = diffNextResult.getPatch(); if (patchNext.isEmpty()) { return mergeResult; } if (current.isEmpty() && (commonAncestor.isEmpty() || next.isEmpty())) { if (commonAncestor.isEmpty()) { mergeResult.setMerged(next); } else if (next.isEmpty()) { mergeResult.getLog().warn("The modification was already applied"); } } else { DiffResult<E> diffCurrentResult; try { diffCurrentResult = diff(commonAncestor, current, null); } catch (DiffException e) { throw new MergeException("Fail to diff between common ancestor and current version", e); } mergeResult.getLog().addAll(diffCurrentResult.getLog()); Patch<E> patchCurrent = diffCurrentResult.getPatch(); mergeResult.setMerged(new ArrayList<>()); if (patchCurrent.isEmpty()) { mergeResult.setMerged(next); } else if (!current.equals(next) && (isFullyModified(commonAncestor, patchCurrent) || isFullyModified(commonAncestor, patchNext))) { Delta<E> deltaNext = nextElement(patchNext); Delta<E> deltaCurrent = nextElement(patchCurrent); List<ConflictDecision<E>> conflictDecisionList = (configuration != null) ? configuration.getConflictDecisionList() : Collections.emptyList(); int newIndex = applyDecision(conflictDecisionList, mergeResult.getMerged(), 0); if (newIndex == Integer.MIN_VALUE) { logConflict(mergeResult, deltaCurrent, deltaNext, commonAncestor, next, current, 0); mergeResult.setMerged(fallback(commonAncestor, next, current, configuration)); } } else { merge(mergeResult, commonAncestor, next, current, patchNext, patchCurrent, configuration); } } return mergeResult; } }
DefaultDiffManager implements DiffManager { @Override public <E> MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current, MergeConfiguration<E> configuration) throws MergeException { DefaultMergeResult<E> mergeResult = new DefaultMergeResult<>(commonAncestor, next, current); DiffResult<E> diffNextResult; try { diffNextResult = diff(commonAncestor, next, null); } catch (DiffException e) { throw new MergeException("Faile to diff between common ancestor and next version", e); } mergeResult.getLog().addAll(diffNextResult.getLog()); Patch<E> patchNext = diffNextResult.getPatch(); if (patchNext.isEmpty()) { return mergeResult; } if (current.isEmpty() && (commonAncestor.isEmpty() || next.isEmpty())) { if (commonAncestor.isEmpty()) { mergeResult.setMerged(next); } else if (next.isEmpty()) { mergeResult.getLog().warn("The modification was already applied"); } } else { DiffResult<E> diffCurrentResult; try { diffCurrentResult = diff(commonAncestor, current, null); } catch (DiffException e) { throw new MergeException("Fail to diff between common ancestor and current version", e); } mergeResult.getLog().addAll(diffCurrentResult.getLog()); Patch<E> patchCurrent = diffCurrentResult.getPatch(); mergeResult.setMerged(new ArrayList<>()); if (patchCurrent.isEmpty()) { mergeResult.setMerged(next); } else if (!current.equals(next) && (isFullyModified(commonAncestor, patchCurrent) || isFullyModified(commonAncestor, patchNext))) { Delta<E> deltaNext = nextElement(patchNext); Delta<E> deltaCurrent = nextElement(patchCurrent); List<ConflictDecision<E>> conflictDecisionList = (configuration != null) ? configuration.getConflictDecisionList() : Collections.emptyList(); int newIndex = applyDecision(conflictDecisionList, mergeResult.getMerged(), 0); if (newIndex == Integer.MIN_VALUE) { logConflict(mergeResult, deltaCurrent, deltaNext, commonAncestor, next, current, 0); mergeResult.setMerged(fallback(commonAncestor, next, current, configuration)); } } else { merge(mergeResult, commonAncestor, next, current, patchNext, patchCurrent, configuration); } } return mergeResult; }  }
DefaultDiffManager implements DiffManager { @Override public <E> MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current, MergeConfiguration<E> configuration) throws MergeException { DefaultMergeResult<E> mergeResult = new DefaultMergeResult<>(commonAncestor, next, current); DiffResult<E> diffNextResult; try { diffNextResult = diff(commonAncestor, next, null); } catch (DiffException e) { throw new MergeException("Faile to diff between common ancestor and next version", e); } mergeResult.getLog().addAll(diffNextResult.getLog()); Patch<E> patchNext = diffNextResult.getPatch(); if (patchNext.isEmpty()) { return mergeResult; } if (current.isEmpty() && (commonAncestor.isEmpty() || next.isEmpty())) { if (commonAncestor.isEmpty()) { mergeResult.setMerged(next); } else if (next.isEmpty()) { mergeResult.getLog().warn("The modification was already applied"); } } else { DiffResult<E> diffCurrentResult; try { diffCurrentResult = diff(commonAncestor, current, null); } catch (DiffException e) { throw new MergeException("Fail to diff between common ancestor and current version", e); } mergeResult.getLog().addAll(diffCurrentResult.getLog()); Patch<E> patchCurrent = diffCurrentResult.getPatch(); mergeResult.setMerged(new ArrayList<>()); if (patchCurrent.isEmpty()) { mergeResult.setMerged(next); } else if (!current.equals(next) && (isFullyModified(commonAncestor, patchCurrent) || isFullyModified(commonAncestor, patchNext))) { Delta<E> deltaNext = nextElement(patchNext); Delta<E> deltaCurrent = nextElement(patchCurrent); List<ConflictDecision<E>> conflictDecisionList = (configuration != null) ? configuration.getConflictDecisionList() : Collections.emptyList(); int newIndex = applyDecision(conflictDecisionList, mergeResult.getMerged(), 0); if (newIndex == Integer.MIN_VALUE) { logConflict(mergeResult, deltaCurrent, deltaNext, commonAncestor, next, current, 0); mergeResult.setMerged(fallback(commonAncestor, next, current, configuration)); } } else { merge(mergeResult, commonAncestor, next, current, patchNext, patchCurrent, configuration); } } return mergeResult; }  @Override DiffResult<E> diff(List<E> previous, List<E> next, DiffConfiguration<E> diff); @Override MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current,
        MergeConfiguration<E> configuration); }
DefaultDiffManager implements DiffManager { @Override public <E> MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current, MergeConfiguration<E> configuration) throws MergeException { DefaultMergeResult<E> mergeResult = new DefaultMergeResult<>(commonAncestor, next, current); DiffResult<E> diffNextResult; try { diffNextResult = diff(commonAncestor, next, null); } catch (DiffException e) { throw new MergeException("Faile to diff between common ancestor and next version", e); } mergeResult.getLog().addAll(diffNextResult.getLog()); Patch<E> patchNext = diffNextResult.getPatch(); if (patchNext.isEmpty()) { return mergeResult; } if (current.isEmpty() && (commonAncestor.isEmpty() || next.isEmpty())) { if (commonAncestor.isEmpty()) { mergeResult.setMerged(next); } else if (next.isEmpty()) { mergeResult.getLog().warn("The modification was already applied"); } } else { DiffResult<E> diffCurrentResult; try { diffCurrentResult = diff(commonAncestor, current, null); } catch (DiffException e) { throw new MergeException("Fail to diff between common ancestor and current version", e); } mergeResult.getLog().addAll(diffCurrentResult.getLog()); Patch<E> patchCurrent = diffCurrentResult.getPatch(); mergeResult.setMerged(new ArrayList<>()); if (patchCurrent.isEmpty()) { mergeResult.setMerged(next); } else if (!current.equals(next) && (isFullyModified(commonAncestor, patchCurrent) || isFullyModified(commonAncestor, patchNext))) { Delta<E> deltaNext = nextElement(patchNext); Delta<E> deltaCurrent = nextElement(patchCurrent); List<ConflictDecision<E>> conflictDecisionList = (configuration != null) ? configuration.getConflictDecisionList() : Collections.emptyList(); int newIndex = applyDecision(conflictDecisionList, mergeResult.getMerged(), 0); if (newIndex == Integer.MIN_VALUE) { logConflict(mergeResult, deltaCurrent, deltaNext, commonAncestor, next, current, 0); mergeResult.setMerged(fallback(commonAncestor, next, current, configuration)); } } else { merge(mergeResult, commonAncestor, next, current, patchNext, patchCurrent, configuration); } } return mergeResult; }  @Override DiffResult<E> diff(List<E> previous, List<E> next, DiffConfiguration<E> diff); @Override MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current,
        MergeConfiguration<E> configuration);  }