|
19 | 19 | import com.github.difflib.patch.Chunk; |
20 | 20 | import com.github.difflib.patch.AbstractDelta; |
21 | 21 | import com.github.difflib.patch.Patch; |
22 | | -import java.util.ArrayList; |
23 | | -import java.util.List; |
24 | | -import java.util.Optional; |
| 22 | + |
| 23 | +import java.util.*; |
25 | 24 | import java.util.regex.Matcher; |
26 | 25 | import java.util.regex.Pattern; |
| 26 | +import java.util.stream.Collectors; |
27 | 27 |
|
28 | 28 | /** |
29 | 29 | * |
@@ -313,4 +313,141 @@ private static List<String> getDeltaText(AbstractDelta<String> delta) { |
313 | 313 |
|
314 | 314 | private UnifiedDiffUtils() { |
315 | 315 | } |
| 316 | + |
| 317 | + /** |
| 318 | + * Compare the differences between two files and return to the original file and diff format |
| 319 | + * |
| 320 | + * (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. |
| 321 | + * You can see all the differences and unmodified places from the original file. |
| 322 | + * Also, this will be very easy and useful for making side-by-side comparison display applications, |
| 323 | + * for example, if you use diff2html (https://github.com/rtfpessoa/diff2html#usage) |
| 324 | + * Wait for tools to display your differences on html pages, you only need to insert the return value into your js code) |
| 325 | + * |
| 326 | + * @param original Original file content |
| 327 | + * @param revised revised file content |
| 328 | + * |
| 329 | + */ |
| 330 | + public static List<String> generateOriginalAndDiff(List<String> original, List<String> revised) { |
| 331 | + return generateOriginalAndDiff(original, revised, null, null); |
| 332 | + } |
| 333 | + |
| 334 | + |
| 335 | + /** |
| 336 | + * Compare the differences between two files and return to the original file and diff format |
| 337 | + * |
| 338 | + * (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. |
| 339 | + * You can see all the differences and unmodified places from the original file. |
| 340 | + * Also, this will be very easy and useful for making side-by-side comparison display applications, |
| 341 | + * for example, if you use diff2html (https://github.com/rtfpessoa/diff2html#usage) |
| 342 | + * Wait for tools to display your differences on html pages, you only need to insert the return value into your js code) |
| 343 | + * |
| 344 | + * @param original Original file content |
| 345 | + * @param revised revised file content |
| 346 | + * @param originalFileName Original file name |
| 347 | + * @param revisedFileName revised file name |
| 348 | + */ |
| 349 | + public static List<String> generateOriginalAndDiff(List<String> original, List<String> revised, String originalFileName, String revisedFileName) { |
| 350 | + originalFileName = originalFileName == null ? "original" : originalFileName; |
| 351 | + revisedFileName = revisedFileName == null ? "revised" : revisedFileName; |
| 352 | + Patch<String> patch = com.github.difflib.DiffUtils.diff(original, revised); |
| 353 | + List<String> unifiedDiff = generateUnifiedDiff(originalFileName, revisedFileName, original, patch, 0); |
| 354 | + if (unifiedDiff.size() == 0) { |
| 355 | + unifiedDiff.add("--- " + originalFileName); |
| 356 | + unifiedDiff.add("+++ " + revisedFileName); |
| 357 | + unifiedDiff.add("@@ -0,0 +0,0 @@"); |
| 358 | + } else if (unifiedDiff.size() >= 3 && !unifiedDiff.get(2).contains("@@ -1,")) { |
| 359 | + unifiedDiff.set(1, unifiedDiff.get(1)); |
| 360 | + unifiedDiff.add(2, "@@ -0,0 +0,0 @@"); |
| 361 | + } |
| 362 | + List<String> original1 = original.stream().map(v -> " " + v).collect(Collectors.toList()); |
| 363 | + return insertOrig(original1, unifiedDiff); |
| 364 | + } |
| 365 | + |
| 366 | + |
| 367 | + //Insert the diff format to the original file |
| 368 | + private static List<String> insertOrig(List<String> original, List<String> unifiedDiff) { |
| 369 | + List<String> result = new ArrayList<>(); |
| 370 | + List<List<String>> diffList = new ArrayList<>(); |
| 371 | + List<String> d = new ArrayList<>(); |
| 372 | + for (int i = 0; i < unifiedDiff.size(); i++) { |
| 373 | + String u = unifiedDiff.get(i); |
| 374 | + if (u.startsWith("@@") && !"@@ -0,0 +0,0 @@".equals(u) && !u.contains("@@ -1,")) { |
| 375 | + List<String> twoList = new ArrayList<>(); |
| 376 | + twoList.addAll(d); |
| 377 | + diffList.add(twoList); |
| 378 | + d.clear(); |
| 379 | + d.add(u); |
| 380 | + continue; |
| 381 | + } |
| 382 | + if (i == unifiedDiff.size() - 1) { |
| 383 | + d.add(u); |
| 384 | + List<String> twoList = new ArrayList<>(); |
| 385 | + twoList.addAll(d); |
| 386 | + diffList.add(twoList); |
| 387 | + d.clear(); |
| 388 | + break; |
| 389 | + } |
| 390 | + d.add(u); |
| 391 | + } |
| 392 | + for (int i = 0; i < diffList.size(); i++) { |
| 393 | + List<String> diff = diffList.get(i); |
| 394 | + List<String> nexDiff = i == diffList.size() - 1 ? null : diffList.get(i + 1); |
| 395 | + String simb = i == 0 ? diff.get(2) : diff.get(0); |
| 396 | + String nexSimb = nexDiff == null ? null : nexDiff.get(0); |
| 397 | + insert(result, diff); |
| 398 | + Map<String, Integer> map = getRowMap(simb); |
| 399 | + if (null != nexSimb) { |
| 400 | + Map<String, Integer> nexMap = getRowMap(nexSimb); |
| 401 | + int start = 0; |
| 402 | + if (map.get("orgRow") != 0) { |
| 403 | + start = map.get("orgRow") + map.get("orgDel") - 1; |
| 404 | + } |
| 405 | + int end = nexMap.get("revRow") - 2; |
| 406 | + insert(result, getOrigList(original, start, end)); |
| 407 | + } |
| 408 | + |
| 409 | + if (simb.contains("@@ -1,") && null == nexSimb && map.get("orgDel") != original.size()) { |
| 410 | + insert(result, getOrigList(original, 0, original.size() - 1)); |
| 411 | + } else if (null == nexSimb && (map.get("orgRow") + map.get("orgDel") - 1) < original.size()) { |
| 412 | + int start = (map.get("orgRow") + map.get("orgDel") - 1); |
| 413 | + start = start == -1 ? 0 : start; |
| 414 | + insert(result, getOrigList(original, start, original.size() - 1)); |
| 415 | + } |
| 416 | + } |
| 417 | + return result; |
| 418 | + } |
| 419 | + |
| 420 | + //Insert the unchanged content in the source file into result |
| 421 | + private static void insert(List<String> result, List<String> noChangeContent) { |
| 422 | + for (String ins : noChangeContent) { |
| 423 | + result.add(ins); |
| 424 | + } |
| 425 | + } |
| 426 | + |
| 427 | + //Parse the line containing @@ to get the modified line number to delete or add a few lines |
| 428 | + private static Map<String, Integer> getRowMap(String str) { |
| 429 | + Map<String, Integer> map = new HashMap<>(); |
| 430 | + if (str.startsWith("@@")) { |
| 431 | + String[] sp = str.split(" "); |
| 432 | + String org = sp[1]; |
| 433 | + String[] orgSp = org.split(","); |
| 434 | + map.put("orgRow", Integer.valueOf(orgSp[0].substring(1))); |
| 435 | + map.put("orgDel", Integer.valueOf(orgSp[1])); |
| 436 | + String[] revSp = org.split(","); |
| 437 | + map.put("revRow", Integer.valueOf(revSp[0].substring(1))); |
| 438 | + map.put("revAdd", Integer.valueOf(revSp[1])); |
| 439 | + } |
| 440 | + return map; |
| 441 | + } |
| 442 | + |
| 443 | + //Get the specified part of the line from the original file |
| 444 | + private static List<String> getOrigList(List<String> original1, int start, int end) { |
| 445 | + List<String> list = new ArrayList<>(); |
| 446 | + if (original1.size() >= 1 && start <= end && end < original1.size()) { |
| 447 | + for (; start <= end; start++) { |
| 448 | + list.add(original1.get(start)); |
| 449 | + } |
| 450 | + } |
| 451 | + return list; |
| 452 | + } |
316 | 453 | } |
0 commit comments