Skip to content

Commit 1664490

Browse files
authored
Add generateOriginalAndDiff method and test class (#164)
* Add generateOriginalAndDiff method and test class * Add generateOriginalAndDiff method and test class.I split long code into short methods, changed ambiguous variable names to explicit variable names * fixes #164 * fix build issues
1 parent 02532a9 commit 1664490

File tree

2 files changed

+195
-0
lines changed

2 files changed

+195
-0
lines changed

java-diff-utils/src/main/java/com/github/difflib/UnifiedDiffUtils.java

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@
1919
import com.github.difflib.patch.Chunk;
2020
import com.github.difflib.patch.AbstractDelta;
2121
import com.github.difflib.patch.Patch;
22+
2223
import java.util.ArrayList;
24+
import java.util.HashMap;
2325
import java.util.List;
26+
import java.util.Map;
2427
import java.util.Optional;
2528
import java.util.regex.Matcher;
2629
import java.util.regex.Pattern;
30+
import java.util.stream.Collectors;
2731

2832
/**
2933
*
@@ -313,4 +317,151 @@ private static List<String> getDeltaText(AbstractDelta<String> delta) {
313317

314318
private UnifiedDiffUtils() {
315319
}
320+
321+
/**
322+
* Compare the differences between two files and return to the original file and diff format
323+
*
324+
* (This method compares the original file with the comparison file to obtain a diff, and inserts the diff into the corresponding position of the original file.
325+
* You can see all the differences and unmodified places from the original file.
326+
* Also, this will be very easy and useful for making side-by-side comparison display applications,
327+
* for example, if you use diff2html (https://github.com/rtfpessoa/diff2html#usage)
328+
* Wait for tools to display your differences on html pages, you only need to insert the return value into your js code)
329+
*
330+
* @param original Original file content
331+
* @param revised revised file content
332+
*
333+
*/
334+
public static List<String> generateOriginalAndDiff(List<String> original, List<String> revised) {
335+
return generateOriginalAndDiff(original, revised, null, null);
336+
}
337+
338+
339+
/**
340+
* Compare the differences between two files and return to the original file and diff format
341+
*
342+
* (This method compares the original file with the comparison file to obtain a diff, and inserts the diff into the corresponding position of the original file.
343+
* You can see all the differences and unmodified places from the original file.
344+
* Also, this will be very easy and useful for making side-by-side comparison display applications,
345+
* for example, if you use diff2html (https://github.com/rtfpessoa/diff2html#usage)
346+
* Wait for tools to display your differences on html pages, you only need to insert the return value into your js code)
347+
*
348+
* @param original Original file content
349+
* @param revised revised file content
350+
* @param originalFileName Original file name
351+
* @param revisedFileName revised file name
352+
*/
353+
public static List<String> generateOriginalAndDiff(List<String> original, List<String> revised, String originalFileName, String revisedFileName) {
354+
String originalFileNameTemp = originalFileName;
355+
String revisedFileNameTemp = originalFileName;
356+
if (originalFileNameTemp == null) {
357+
originalFileNameTemp = "original";
358+
}
359+
if (revisedFileNameTemp == null) {
360+
revisedFileNameTemp = "revised";
361+
}
362+
Patch<String> patch = DiffUtils.diff(original, revised);
363+
List<String> unifiedDiff = generateUnifiedDiff(originalFileNameTemp, revisedFileNameTemp, original, patch, 0);
364+
if (unifiedDiff.isEmpty()) {
365+
unifiedDiff.add("--- " + originalFileNameTemp);
366+
unifiedDiff.add("+++ " + revisedFileNameTemp);
367+
unifiedDiff.add("@@ -0,0 +0,0 @@");
368+
} else if (unifiedDiff.size() >= 3 && !unifiedDiff.get(2).contains("@@ -1,")) {
369+
unifiedDiff.set(1, unifiedDiff.get(1));
370+
unifiedDiff.add(2, "@@ -0,0 +0,0 @@");
371+
}
372+
List<String> originalWithPrefix = original.stream().map(v -> " " + v).collect(Collectors.toList());
373+
return insertOrig(originalWithPrefix, unifiedDiff);
374+
}
375+
376+
//Insert the diff format to the original file
377+
private static List<String> insertOrig(List<String> original, List<String> unifiedDiff) {
378+
List<String> result = new ArrayList<>();
379+
List<List<String>> diffList = new ArrayList<>();
380+
List<String> diff = new ArrayList<>();
381+
for (int i = 0; i < unifiedDiff.size(); i++) {
382+
String u = unifiedDiff.get(i);
383+
if (u.startsWith("@@") && !"@@ -0,0 +0,0 @@".equals(u) && !u.contains("@@ -1,")) {
384+
List<String> twoList = new ArrayList<>();
385+
twoList.addAll(diff);
386+
diffList.add(twoList);
387+
diff.clear();
388+
diff.add(u);
389+
continue;
390+
}
391+
if (i == unifiedDiff.size() - 1) {
392+
diff.add(u);
393+
List<String> twoList = new ArrayList<>();
394+
twoList.addAll(diff);
395+
diffList.add(twoList);
396+
diff.clear();
397+
break;
398+
}
399+
diff.add(u);
400+
}
401+
insertOrig(diffList, result, original);
402+
return result;
403+
}
404+
405+
//Insert the diff format to the original file
406+
private static void insertOrig(List<List<String>> diffList, List<String> result, List<String> original) {
407+
for (int i = 0; i < diffList.size(); i++) {
408+
List<String> diff = diffList.get(i);
409+
List<String> nexDiff = i == diffList.size() - 1 ? null : diffList.get(i + 1);
410+
String simb = i == 0 ? diff.get(2) : diff.get(0);
411+
String nexSimb = nexDiff == null ? null : nexDiff.get(0);
412+
insert(result, diff);
413+
Map<String, Integer> map = getRowMap(simb);
414+
if (null != nexSimb) {
415+
Map<String, Integer> nexMap = getRowMap(nexSimb);
416+
int start = 0;
417+
if (map.get("orgRow") != 0) {
418+
start = map.get("orgRow") + map.get("orgDel") - 1;
419+
}
420+
int end = nexMap.get("revRow") - 2;
421+
insert(result, getOrigList(original, start, end));
422+
}
423+
if (simb.contains("@@ -1,") && null == nexSimb && map.get("orgDel") != original.size()) {
424+
insert(result, getOrigList(original, 0, original.size() - 1));
425+
} else if (null == nexSimb && (map.get("orgRow") + map.get("orgDel") - 1) < original.size()) {
426+
int start = map.get("orgRow") + map.get("orgDel") - 1;
427+
start = start == -1 ? 0 : start;
428+
insert(result, getOrigList(original, start, original.size() - 1));
429+
}
430+
}
431+
}
432+
433+
//Insert the unchanged content in the source file into result
434+
private static void insert(List<String> result, List<String> noChangeContent) {
435+
for (String ins : noChangeContent) {
436+
result.add(ins);
437+
}
438+
}
439+
440+
//Parse the line containing @@ to get the modified line number to delete or add a few lines
441+
private static Map<String, Integer> getRowMap(String str) {
442+
Map<String, Integer> map = new HashMap<>();
443+
if (str.startsWith("@@")) {
444+
String[] sp = str.split(" ");
445+
String org = sp[1];
446+
String[] orgSp = org.split(",");
447+
map.put("orgRow", Integer.valueOf(orgSp[0].substring(1)));
448+
map.put("orgDel", Integer.valueOf(orgSp[1]));
449+
String[] revSp = org.split(",");
450+
map.put("revRow", Integer.valueOf(revSp[0].substring(1)));
451+
map.put("revAdd", Integer.valueOf(revSp[1]));
452+
}
453+
return map;
454+
}
455+
456+
//Get the specified part of the line from the original file
457+
private static List<String> getOrigList(List<String> originalWithPrefix, int start, int end) {
458+
List<String> list = new ArrayList<>();
459+
if (originalWithPrefix.size() >= 1 && start <= end && end < originalWithPrefix.size()) {
460+
int startTemp = start;
461+
for (; startTemp <= end; startTemp++) {
462+
list.add(originalWithPrefix.get(startTemp));
463+
}
464+
}
465+
return list;
466+
}
316467
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.github.difflib.examples;
2+
3+
import com.github.difflib.TestConstants;
4+
import com.github.difflib.UnifiedDiffUtils;
5+
import org.junit.jupiter.api.Test;
6+
7+
import java.io.BufferedReader;
8+
import java.io.FileNotFoundException;
9+
import java.io.FileReader;
10+
import java.io.IOException;
11+
import java.util.ArrayList;
12+
import java.util.List;
13+
14+
import static java.util.stream.Collectors.joining;
15+
import static org.junit.jupiter.api.Assertions.fail;
16+
17+
public class OriginalAndDiffTest {
18+
19+
@Test
20+
public void testGenerateOriginalAndDiff() {
21+
List<String> origLines = null;
22+
List<String> revLines = null;
23+
try {
24+
origLines = fileToLines(TestConstants.MOCK_FOLDER + "original.txt");
25+
revLines = fileToLines(TestConstants.MOCK_FOLDER + "revised.txt");
26+
} catch (IOException e) {
27+
fail(e.getMessage());
28+
}
29+
30+
List<String> originalAndDiff = UnifiedDiffUtils.generateOriginalAndDiff(origLines, revLines);
31+
System.out.println(originalAndDiff.stream().collect(joining("\n")));
32+
}
33+
34+
public static List<String> fileToLines(String filename) throws FileNotFoundException, IOException {
35+
List<String> lines = new ArrayList<>();
36+
String line = "";
37+
try (BufferedReader in = new BufferedReader(new FileReader(filename))) {
38+
while ((line = in.readLine()) != null) {
39+
lines.add(line);
40+
}
41+
}
42+
return lines;
43+
}
44+
}

0 commit comments

Comments
 (0)