17
17
18
18
import com .github .difflib .DiffUtils ;
19
19
import com .github .difflib .patch .AbstractDelta ;
20
+ import com .github .difflib .patch .ChangeDelta ;
20
21
import com .github .difflib .patch .Chunk ;
22
+ import com .github .difflib .patch .DeleteDelta ;
21
23
import com .github .difflib .patch .DeltaType ;
24
+ import com .github .difflib .patch .InsertDelta ;
22
25
import com .github .difflib .patch .Patch ;
23
26
import com .github .difflib .text .DiffRow .Tag ;
24
27
import java .util .*;
30
33
import static java .util .stream .Collectors .toList ;
31
34
32
35
/**
33
- * This class for generating DiffRows for side-by-sidy view. You can customize the way of
34
- * generating. For example, show inline diffs on not, ignoring white spaces or/and blank lines and
35
- * so on. All parameters for generating are optional. If you do not specify them, the class will use
36
- * the default values.
36
+ * This class for generating DiffRows for side-by-sidy view. You can customize
37
+ * the way of generating. For example, show inline diffs on not, ignoring white
38
+ * spaces or/and blank lines and so on. All parameters for generating are
39
+ * optional. If you do not specify them, the class will use the default values.
37
40
*
38
- * These values are: showInlineDiffs = false; ignoreWhiteSpaces = true; ignoreBlankLines = true; ...
41
+ * These values are: showInlineDiffs = false; ignoreWhiteSpaces = true;
42
+ * ignoreBlankLines = true; ...
39
43
*
40
- * For instantiating the DiffRowGenerator you should use the its builder. Like in example <code>
44
+ * For instantiating the DiffRowGenerator you should use the its builder. Like
45
+ * in example <code>
41
46
* DiffRowGenerator generator = new DiffRowGenerator.Builder().showInlineDiffs(true).
42
47
* ignoreWhiteSpaces(true).columnWidth(100).build();
43
48
* </code>
@@ -100,8 +105,8 @@ protected final static List<String> splitStringPreserveDelimiter(String str, Pat
100
105
/**
101
106
* Wrap the elements in the sequence with the given tag
102
107
*
103
- * @param startPosition the position from which tag should start. The counting start from a
104
- * zero.
108
+ * @param startPosition the position from which tag should start. The
109
+ * counting start from a zero.
105
110
* @param endPosition the position before which tag should should be closed.
106
111
* @param tagGenerator the tag generator
107
112
*/
@@ -187,16 +192,16 @@ private DiffRowGenerator(Builder builder) {
187
192
reportLinesUnchanged = builder .reportLinesUnchanged ;
188
193
lineNormalizer = builder .lineNormalizer ;
189
194
processDiffs = builder .processDiffs ;
190
-
195
+
191
196
replaceOriginalLinefeedInChangesWithSpaces = builder .replaceOriginalLinefeedInChangesWithSpaces ;
192
197
193
198
Objects .requireNonNull (inlineDiffSplitter );
194
199
Objects .requireNonNull (lineNormalizer );
195
200
}
196
201
197
202
/**
198
- * Get the DiffRows describing the difference between original and revised texts using the given
199
- * patch. Useful for displaying side-by-side diff.
203
+ * Get the DiffRows describing the difference between original and revised
204
+ * texts using the given patch. Useful for displaying side-by-side diff.
200
205
*
201
206
* @param original the original text
202
207
* @param revised the revised text
@@ -207,8 +212,9 @@ public List<DiffRow> generateDiffRows(List<String> original, List<String> revise
207
212
}
208
213
209
214
/**
210
- * Generates the DiffRows describing the difference between original and revised texts using the
211
- * given patch. Useful for displaying side-by-side diff.
215
+ * Generates the DiffRows describing the difference between original and
216
+ * revised texts using the given patch. Useful for displaying side-by-side
217
+ * diff.
212
218
*
213
219
* @param original the original text
214
220
* @param patch the given patch
@@ -218,6 +224,9 @@ public List<DiffRow> generateDiffRows(final List<String> original, Patch<String>
218
224
List <DiffRow > diffRows = new ArrayList <>();
219
225
int endPos = 0 ;
220
226
final List <AbstractDelta <String >> deltaList = patch .getDeltas ();
227
+
228
+ decompressDeltas (deltaList );
229
+
221
230
for (AbstractDelta <String > delta : deltaList ) {
222
231
Chunk <String > orig = delta .getSource ();
223
232
Chunk <String > rev = delta .getTarget ();
@@ -263,6 +272,44 @@ public List<DiffRow> generateDiffRows(final List<String> original, Patch<String>
263
272
return diffRows ;
264
273
}
265
274
275
+ /**
276
+ * Decompresses ChangeDeltas with different source and target size to a ChangeDelta with same size and
277
+ * a following InsertDelta or DeleteDelta. With this problems of building DiffRows getting smaller.
278
+ * @param deltaList
279
+ */
280
+ private void decompressDeltas (final List <AbstractDelta <String >> deltaList ) {
281
+ for (int idx = 0 ; idx < deltaList .size (); idx ++) {
282
+ AbstractDelta <String > delta = deltaList .get (idx );
283
+ if (delta .getType () == DeltaType .CHANGE && delta .getSource ().size () != delta .getTarget ().size ()) {
284
+ //System.out.println("decompress this " + delta);
285
+
286
+ List <AbstractDelta <String >> corrected = new ArrayList <>();
287
+ int minSize = Math .min (delta .getSource ().size (), delta .getTarget ().size ());
288
+ Chunk <String > orig = delta .getSource ();
289
+ Chunk <String > rev = delta .getTarget ();
290
+
291
+ deltaList .set (idx , new ChangeDelta <String >(
292
+ new Chunk <>(orig .getPosition (), orig .getLines ().subList (0 , minSize )),
293
+ new Chunk <>(rev .getPosition (), rev .getLines ().subList (0 , minSize ))));
294
+
295
+ if (orig .getLines ().size () < rev .getLines ().size ()) {
296
+ deltaList .add (idx + 1 , new InsertDelta <String >(
297
+ new Chunk <>(orig .getPosition () + minSize , Collections .emptyList ()),
298
+ new Chunk <>(rev .getPosition () + minSize , rev .getLines ().subList (minSize , rev .getLines ().size ()))));
299
+ } else {
300
+ deltaList .add (idx + 1 , new DeleteDelta <String >(
301
+ new Chunk <>(orig .getPosition () + minSize , orig .getLines ().subList (minSize , orig .getLines ().size ())),
302
+ new Chunk <>(rev .getPosition () + minSize , Collections .emptyList ())));
303
+ }
304
+
305
+ //System.out.println(" to " + corrected);
306
+ }
307
+ idx ++;
308
+ }
309
+
310
+ //System.out.println("got now " + deltaList);
311
+ }
312
+
266
313
private DiffRow buildDiffRow (Tag type , String orgline , String newline ) {
267
314
if (reportLinesUnchanged ) {
268
315
return new DiffRow (type , orgline , newline );
@@ -436,8 +483,8 @@ public Builder ignoreWhiteSpaces(boolean val) {
436
483
}
437
484
438
485
/**
439
- * Give the originial old and new text lines to Diffrow without any additional processing
440
- * and without any tags to highlight the change.
486
+ * Give the originial old and new text lines to Diffrow without any
487
+ * additional processing and without any tags to highlight the change.
441
488
*
442
489
* @param val the value to set. Default: false.
443
490
* @return builder with configured reportLinesUnWrapped parameter
@@ -492,8 +539,8 @@ public Builder newTag(Function<Boolean, String> generator) {
492
539
}
493
540
494
541
/**
495
- * Processor for diffed text parts. Here e.g. whitecharacters could be replaced by something
496
- * visible.
542
+ * Processor for diffed text parts. Here e.g. whitecharacters could be
543
+ * replaced by something visible.
497
544
*
498
545
* @param processDiffs
499
546
* @return
@@ -504,10 +551,11 @@ public Builder processDiffs(Function<String, String> processDiffs) {
504
551
}
505
552
506
553
/**
507
- * Set the column width of generated lines of original and revised texts.
554
+ * Set the column width of generated lines of original and revised
555
+ * texts.
508
556
*
509
- * @param width the width to set. Making it < 0 doesn't make any sense. Default 80.
510
- * @return builder with config of column width
557
+ * @param width the width to set. Making it < 0 doesn't make any sense.
558
+ * Default 80. @return builder with config of column width
511
559
*/
512
560
public Builder columnWidth (int width ) {
513
561
if (width >= 0 ) {
@@ -517,7 +565,8 @@ public Builder columnWidth(int width) {
517
565
}
518
566
519
567
/**
520
- * Build the DiffRowGenerator. If some parameters is not set, the default values are used.
568
+ * Build the DiffRowGenerator. If some parameters is not set, the
569
+ * default values are used.
521
570
*
522
571
* @return the customized DiffRowGenerator
523
572
*/
@@ -526,8 +575,8 @@ public DiffRowGenerator build() {
526
575
}
527
576
528
577
/**
529
- * Merge the complete result within the original text. This makes sense for one line
530
- * display.
578
+ * Merge the complete result within the original text. This makes sense
579
+ * for one line display.
531
580
*
532
581
* @param mergeOriginalRevised
533
582
* @return
@@ -538,9 +587,9 @@ public Builder mergeOriginalRevised(boolean mergeOriginalRevised) {
538
587
}
539
588
540
589
/**
541
- * Per default each character is separatly processed. This variant introduces processing by
542
- * word, which does not deliver in word changes. Therefore the whole word will be tagged as
543
- * changed:
590
+ * Per default each character is separatly processed. This variant
591
+ * introduces processing by word, which does not deliver in word
592
+ * changes. Therefore the whole word will be tagged as changed:
544
593
*
545
594
* <pre>
546
595
* false: (aBa : aba) -- changed: a(B)a : a(b)a
@@ -553,8 +602,9 @@ public Builder inlineDiffByWord(boolean inlineDiffByWord) {
553
602
}
554
603
555
604
/**
556
- * To provide some customized splitting a splitter can be provided. Here someone could think
557
- * about sentence splitter, comma splitter or stuff like that.
605
+ * To provide some customized splitting a splitter can be provided. Here
606
+ * someone could think about sentence splitter, comma splitter or stuff
607
+ * like that.
558
608
*
559
609
* @param inlineDiffSplitter
560
610
* @return
@@ -565,9 +615,10 @@ public Builder inlineDiffBySplitter(Function<String, List<String>> inlineDiffSpl
565
615
}
566
616
567
617
/**
568
- * By default DiffRowGenerator preprocesses lines for HTML output. Tabs and special HTML
569
- * characters like "<" are replaced with its encoded value. To change this you can
570
- * provide a customized line normalizer here.
618
+ * By default DiffRowGenerator preprocesses lines for HTML output. Tabs
619
+ * and special HTML characters like "<" are replaced with its encoded
620
+ * value. To change this you can provide a customized line normalizer
621
+ * here.
571
622
*
572
623
* @param lineNormalizer
573
624
* @return
@@ -587,13 +638,14 @@ public Builder equalizer(BiPredicate<String, String> equalizer) {
587
638
this .equalizer = equalizer ;
588
639
return this ;
589
640
}
590
-
641
+
591
642
/**
592
- * Sometimes it happens that a change contains multiple lines. If there is no correspondence
593
- * in old and new. To keep the merged line more readable the linefeeds could be replaced
594
- * by spaces.
643
+ * Sometimes it happens that a change contains multiple lines. If there
644
+ * is no correspondence in old and new. To keep the merged line more
645
+ * readable the linefeeds could be replaced by spaces.
646
+ *
595
647
* @param replace
596
- * @return
648
+ * @return
597
649
*/
598
650
public Builder replaceOriginalLinefeedInChangesWithSpaces (boolean replace ) {
599
651
this .replaceOriginalLinefeedInChangesWithSpaces = replace ;
0 commit comments