int (final List<? extends PatchLine> lines, final List<? super String> contextBefore, final List<? super String> contextAfter, final List<? super BeforeAfter<List<String>>> steps, final int startI) { int i = startI; for (; i < lines.size(); i++) { final PatchLine patchLine = lines.get(i); if (PatchLine.Type.CONTEXT != patchLine.getType()) break; contextBefore.add(patchLine.getText()); } final boolean addFirst = i < lines.size() && PatchLine.Type.ADD == lines.get(i).getType(); List<String> before = new ArrayList<>(); List<String> after = new ArrayList<>(); for (; i < lines.size(); i++) { final PatchLine patchLine = lines.get(i); final PatchLine.Type type = patchLine.getType(); if (PatchLine.Type.CONTEXT == type) { break; } if (PatchLine.Type.ADD == type) { if (addFirst && ! before.isEmpty()) { // new piece steps.add(new BeforeAfter<>(before, after)); before = new ArrayList<>(); after = new ArrayList<>(); } after.add(patchLine.getText()); } else if (PatchLine.Type.REMOVE == type) { if (! addFirst && ! after.isEmpty()) { // new piece steps.add(new BeforeAfter<>(before, after)); before = new ArrayList<>(); after = new ArrayList<>(); } before.add(patchLine.getText()); } } if (! before.isEmpty() || ! after.isEmpty()) { steps.add(new BeforeAfter<>(before, after)); } for (; i < lines.size(); i++) { final PatchLine patchLine = lines.get(i); if (PatchLine.Type.CONTEXT != patchLine.getType()) { return i; } contextAfter.add(patchLine.getText()); } return lines.size(); }