16
16
package difflib ;
17
17
18
18
import difflib .DiffRow .Tag ;
19
+ import difflib .myers .Equalizer ;
19
20
20
21
import java .util .*;
21
22
22
23
/**
23
24
* This class for generating DiffRows for side-by-sidy view.
24
- * You can customize the way of generating. For example, show inline diffs on not, ignoring
25
+ * You can customize the way of generating. For example, show inline diffs on not, ignoring
25
26
* white spaces or/and blank lines and so on. All parameters for generating are optional. If you do
26
27
* not specify them, the class will use the default values.
27
- *
28
+ *
28
29
* These values are:
29
30
* showInlineDiffs = false;
30
31
* ignoreWhiteSpaces = true;
31
32
* ignoreBlankLines = true;
32
33
* ...
33
- *
34
+ *
34
35
* For instantiating the DiffRowGenerator you should use the its builder. Like in example
35
36
* <code>
36
37
* DiffRowGenerator generator = new DiffRowGenerator.Builder().showInlineDiffs(true).
37
38
* ignoreWhiteSpaces(true).columnWidth(100).build();
38
39
* </code>
39
- *
40
+ *
40
41
* @author <a href="[email protected] ">Dmitry Naumenko</a>
41
42
*/
42
43
public class DiffRowGenerator {
@@ -48,32 +49,33 @@ public class DiffRowGenerator {
48
49
private final String InlineOldCssClass ;
49
50
private final String InlineNewCssClass ;
50
51
private final int columnWidth ;
51
-
52
+ private final Equalizer equalizer ;
53
+
52
54
/**
53
55
* This class used for building the DiffRowGenerator.
54
56
* @author dmitry
55
57
*
56
58
*/
57
59
public static class Builder {
58
60
private boolean showInlineDiffs = false ;
59
- private boolean ignoreWhiteSpaces = true ;
60
- private boolean ignoreBlankLines = true ;
61
+ private boolean ignoreWhiteSpaces = false ;
62
+ private boolean ignoreBlankLines = false ;
61
63
private String InlineOldTag = "span" ;
62
64
private String InlineNewTag = "span" ;
63
65
private String InlineOldCssClass = "editOldInline" ;
64
66
private String InlineNewCssClass = "editNewInline" ;
65
67
private int columnWidth = 80 ;
66
-
68
+
67
69
/**
68
70
* Show inline diffs in generating diff rows or not.
69
71
* @param val the value to set. Default: false.
70
- * @return builder with configured showInlineDiff parameter
72
+ * @return builder with configured showInlineDiff parameter
71
73
*/
72
74
public Builder showInlineDiffs (boolean val ) {
73
75
showInlineDiffs = val ;
74
76
return this ;
75
77
}
76
-
78
+
77
79
/**
78
80
* Ignore white spaces in generating diff rows or not.
79
81
* @param val the value to set. Default: true.
@@ -83,7 +85,7 @@ public Builder ignoreWhiteSpaces(boolean val) {
83
85
ignoreWhiteSpaces = val ;
84
86
return this ;
85
87
}
86
-
88
+
87
89
/**
88
90
* Ignore blank lines in generating diff rows or not.
89
91
* @param val the value to set. Default: true.
@@ -93,7 +95,7 @@ public Builder ignoreBlankLines(boolean val) {
93
95
ignoreBlankLines = val ;
94
96
return this ;
95
97
}
96
-
98
+
97
99
/**
98
100
* Set the tag used for displaying changes in the original text.
99
101
* @param tag the tag to set. Without angle brackets. Default: span.
@@ -103,7 +105,7 @@ public Builder InlineOldTag(String tag) {
103
105
InlineOldTag = tag ;
104
106
return this ;
105
107
}
106
-
108
+
107
109
/**
108
110
* Set the tag used for displaying changes in the revised text.
109
111
* @param tag the tag to set. Without angle brackets. Default: span.
@@ -113,7 +115,7 @@ public Builder InlineNewTag(String tag) {
113
115
InlineNewTag = tag ;
114
116
return this ;
115
117
}
116
-
118
+
117
119
/**
118
120
* Set the css class used for displaying changes in the original text.
119
121
* @param cssClass the tag to set. Without any quotes, just word. Default: editOldInline.
@@ -123,7 +125,7 @@ public Builder InlineOldCssClass(String cssClass) {
123
125
InlineOldCssClass = cssClass ;
124
126
return this ;
125
127
}
126
-
128
+
127
129
/**
128
130
* Set the css class used for displaying changes in the revised text.
129
131
* @param cssClass the tag to set. Without any quotes, just word. Default: editNewInline.
@@ -133,7 +135,7 @@ public Builder InlineNewCssClass(String cssClass) {
133
135
InlineNewCssClass = cssClass ;
134
136
return this ;
135
137
}
136
-
138
+
137
139
/**
138
140
* Set the column with of generated lines of original and revised texts.
139
141
* @param width the width to set. Making it < 0 doesn't have any sense. Default 80.
@@ -145,7 +147,7 @@ public Builder columnWidth(int width) {
145
147
}
146
148
return this ;
147
149
}
148
-
150
+
149
151
/**
150
152
* Build the DiffRowGenerator. If some parameters is not set, the default values are used.
151
153
* @return the customized DiffRowGenerator
@@ -154,7 +156,7 @@ public DiffRowGenerator build() {
154
156
return new DiffRowGenerator (this );
155
157
}
156
158
}
157
-
159
+
158
160
private DiffRowGenerator (Builder builder ) {
159
161
showInlineDiffs = builder .showInlineDiffs ;
160
162
ignoreWhiteSpaces = builder .ignoreWhiteSpaces ; //
@@ -164,59 +166,79 @@ private DiffRowGenerator(Builder builder) {
164
166
InlineOldCssClass = builder .InlineOldCssClass ;
165
167
InlineNewCssClass = builder .InlineNewCssClass ;
166
168
columnWidth = builder .columnWidth ; //
169
+ equalizer = new Equalizer () {
170
+ public boolean equals (Object original , Object revised ) {
171
+ if (ignoreWhiteSpaces ) {
172
+ original = ((String )original ).trim ().replaceAll ("\\ s+" , " " );
173
+ revised = ((String )revised ).trim ().replaceAll ("\\ s+" , " " );
174
+ }
175
+ return original .equals (revised );
176
+ }
177
+ };
167
178
}
168
-
179
+
169
180
/**
170
181
* Get the DiffRows describing the difference between original and revised texts using the
171
182
* given patch. Useful for displaying side-by-side diff.
172
- *
183
+ *
173
184
* @param original the original text
174
- * @param revised the revised text
185
+ * @param revised the revised text
175
186
* @return the DiffRows between original and revised texts
176
187
*/
177
188
public List <DiffRow > generateDiffRows (List <String > original , List <String > revised ) {
178
- return generateDiffRows (original , revised , DiffUtils .diff (original , revised ));
189
+ return generateDiffRows (original , revised , DiffUtils .diff (original , revised , equalizer ));
190
+ }
191
+
192
+ private List <String > removeBlankLines (List <String > lines ) {
193
+ List <String > result = new ArrayList <String >();
194
+ for (String line : lines ) {
195
+ if (line .trim ().length () == 0 ) {
196
+ result .add ("" );
197
+ }
198
+ result .add (line );
199
+ }
200
+ return result ;
179
201
}
180
-
202
+
181
203
/**
182
204
* Generates the DiffRows describing the difference between original and revised texts using the
183
205
* given patch. Useful for displaying side-by-side diff.
184
- *
206
+ *
185
207
* @param original the original text
186
208
* @param revised the revised text
187
- * @param patch the given patch
209
+ * @param patch the given patch
188
210
* @return the DiffRows between original and revised texts
189
211
*/
190
212
@ SuppressWarnings ("unchecked" )
191
213
public List <DiffRow > generateDiffRows (List <String > original , List <String > revised , Patch patch ) {
192
214
// normalize the lines (expand tabs, escape html entities)
193
215
original = StringUtills .normalize (original );
194
216
revised = StringUtills .normalize (revised );
195
-
217
+
196
218
// wrap to the column width
197
219
original = StringUtills .wrapText (original , this .columnWidth );
198
220
revised = StringUtills .wrapText (revised , this .columnWidth );
199
-
221
+
200
222
List <DiffRow > diffRows = new ArrayList <DiffRow >();
201
223
int endPos = 0 ;
202
224
final List <Delta > deltaList = patch .getDeltas ();
203
225
for (int i = 0 ; i < deltaList .size (); i ++) {
204
226
Delta delta = deltaList .get (i );
205
227
Chunk orig = delta .getOriginal ();
206
228
Chunk rev = delta .getRevised ();
207
-
229
+
208
230
// We should normalize and wrap lines in deltas too.
209
231
orig .setLines (StringUtills .normalize ((List <String >) orig .getLines ()));
210
232
rev .setLines (StringUtills .normalize ((List <String >) rev .getLines ()));
211
-
233
+
212
234
orig .setLines (StringUtills .wrapText ((List <String >) orig .getLines (), this .columnWidth ));
213
235
rev .setLines (StringUtills .wrapText ((List <String >) rev .getLines (), this .columnWidth ));
214
-
236
+
215
237
// catch the equal prefix for each chunk
216
238
for (String line : original .subList (endPos , orig .getPosition ())) {
217
239
diffRows .add (new DiffRow (Tag .EQUAL , line , line ));
218
240
}
219
-
241
+
220
242
// Inserted DiffRow
221
243
if (delta .getClass ().equals (InsertDelta .class )) {
222
244
endPos = orig .last () + 1 ;
@@ -225,7 +247,7 @@ public List<DiffRow> generateDiffRows(List<String> original, List<String> revise
225
247
}
226
248
continue ;
227
249
}
228
-
250
+
229
251
// Deleted DiffRow
230
252
if (delta .getClass ().equals (DeleteDelta .class )) {
231
253
endPos = orig .last () + 1 ;
@@ -234,7 +256,7 @@ public List<DiffRow> generateDiffRows(List<String> original, List<String> revise
234
256
}
235
257
continue ;
236
258
}
237
-
259
+
238
260
if (showInlineDiffs ) {
239
261
addInlineDiffs (delta );
240
262
}
@@ -257,14 +279,14 @@ public List<DiffRow> generateDiffRows(List<String> original, List<String> revise
257
279
}
258
280
endPos = orig .last () + 1 ;
259
281
}
260
-
282
+
261
283
// Copy the final matching chunk if any.
262
284
for (String line : original .subList (endPos , original .size ())) {
263
285
diffRows .add (new DiffRow (Tag .EQUAL , line , line ));
264
286
}
265
287
return diffRows ;
266
288
}
267
-
289
+
268
290
/**
269
291
* Add the inline diffs for given delta
270
292
* @param delta the given delta
@@ -313,12 +335,12 @@ private void addInlineDiffs(Delta delta) {
313
335
delta .getRevised ().setLines (Arrays .asList (revResult .toString ().split ("\n " )));
314
336
}
315
337
}
316
-
338
+
317
339
/**
318
340
* Wrap the elements in the sequence with the given tag
319
341
* @param startPosition the position from which tag should start. The counting start from a zero.
320
- * @param endPosition the position before which tag should should be closed.
321
- * @param tag the tag name without angle brackets, just a word
342
+ * @param endPosition the position before which tag should should be closed.
343
+ * @param tag the tag name without angle brackets, just a word
322
344
* @param cssClass the optional css class
323
345
*/
324
346
public static LinkedList <String > wrapInTag (LinkedList <String > sequence , int startPosition ,
@@ -334,23 +356,23 @@ public static LinkedList<String> wrapInTag(LinkedList<String> sequence, int star
334
356
}
335
357
tagBuilder .append (">" );
336
358
String startTag = tagBuilder .toString ();
337
-
359
+
338
360
tagBuilder .delete (0 , tagBuilder .length ());
339
-
361
+
340
362
tagBuilder .append ("</" );
341
363
tagBuilder .append (tag );
342
364
tagBuilder .append (">" );
343
365
String endTag = tagBuilder .toString ();
344
-
366
+
345
367
result .add (startPosition , startTag );
346
368
result .add (endPosition , endTag );
347
369
return result ;
348
370
}
349
-
371
+
350
372
/**
351
373
* Wrap the given line with the given tag
352
374
* @param line the given line
353
- * @param tag the tag name without angle brackets, just a word
375
+ * @param tag the tag name without angle brackets, just a word
354
376
* @param cssClass the optional css class
355
377
* @return the wrapped string
356
378
*/
@@ -365,17 +387,17 @@ public static String wrapInTag(String line, String tag, String cssClass) {
365
387
}
366
388
tagBuilder .append (">" );
367
389
String startTag = tagBuilder .toString ();
368
-
390
+
369
391
tagBuilder .delete (0 , tagBuilder .length ());
370
-
392
+
371
393
tagBuilder .append ("</" );
372
394
tagBuilder .append (tag );
373
395
tagBuilder .append (">" );
374
396
String endTag = tagBuilder .toString ();
375
-
397
+
376
398
return startTag + line + endTag ;
377
399
}
378
-
400
+
379
401
/**
380
402
* The helper method for joining collections
381
403
* @param <T>
0 commit comments