@@ -56,6 +56,7 @@ public class DiffRowGenerator {
5656 private final String inlineNewCssClass ;
5757 private final int columnWidth ;
5858 private final Equalizer <String > equalizer ;
59+ private final boolean mergeInline ;
5960
6061 /**
6162 * This class used for building the DiffRowGenerator.
@@ -72,6 +73,7 @@ public static class Builder {
7273 private String inlineOldCssClass = "editOldInline" ;
7374 private String inlineNewCssClass = "editNewInline" ;
7475 private int columnWidth = 80 ;
76+ private boolean mergeInline = false ;
7577
7678 private Builder () {
7779 }
@@ -163,6 +165,12 @@ public Builder columnWidth(int width) {
163165 public DiffRowGenerator build () {
164166 return new DiffRowGenerator (this );
165167 }
168+
169+ public Builder mergeInline (boolean mergeInline ) {
170+ this .mergeInline = mergeInline ;
171+ return this ;
172+ }
173+
166174 }
167175
168176 public static Builder create () {
@@ -171,12 +179,13 @@ public static Builder create() {
171179
172180 private DiffRowGenerator (Builder builder ) {
173181 showInlineDiffs = builder .showInlineDiffs ;
174- ignoreWhiteSpaces = builder .ignoreWhiteSpaces ; //
182+ ignoreWhiteSpaces = builder .ignoreWhiteSpaces ;
175183 inlineOldTag = builder .inlineOldTag ;
176184 inlineNewTag = builder .inlineNewTag ;
177185 inlineOldCssClass = builder .inlineOldCssClass ;
178186 inlineNewCssClass = builder .inlineNewCssClass ;
179- columnWidth = builder .columnWidth ; //
187+ columnWidth = builder .columnWidth ;
188+ mergeInline = builder .mergeInline ;
180189 equalizer = new Equalizer <String >() {
181190 @ Override
182191 public boolean equals (String original , String revised ) {
@@ -202,9 +211,21 @@ public List<DiffRow> generateDiffRows(List<String> original, List<String> revise
202211 }
203212
204213 private DiffRow buildDiffRow (Tag type , String orgline , String newline ) {
205- return new DiffRow (type ,
206- StringUtils .wrapText (StringUtils .normalize (orgline ), columnWidth ),
207- StringUtils .wrapText (StringUtils .normalize (newline ), columnWidth ));
214+ String wrapOrg = StringUtils .wrapText (StringUtils .normalize (orgline ), columnWidth );
215+ if (showInlineDiffs && Tag .DELETE == type ) {
216+ wrapOrg = createOpenTag (inlineOldTag , inlineOldCssClass ) + wrapOrg + createCloseTag (inlineOldTag );
217+ }
218+ String wrapNew = StringUtils .wrapText (StringUtils .normalize (newline ), columnWidth );
219+ if (showInlineDiffs && Tag .INSERT == type ) {
220+ wrapOrg = createOpenTag (inlineNewTag , inlineNewCssClass ) + wrapNew + createCloseTag (inlineNewTag );
221+ }
222+ return new DiffRow (type , wrapOrg , wrapNew );
223+ }
224+
225+ private DiffRow buildDiffRowWithoutNormalizing (Tag type , String orgline , String newline ) {
226+ return new DiffRow (type ,
227+ StringUtils .wrapText (orgline , columnWidth ),
228+ StringUtils .wrapText (newline , columnWidth ));
208229 }
209230
210231 /**
@@ -217,14 +238,6 @@ private DiffRow buildDiffRow(Tag type, String orgline, String newline) {
217238 * @return the DiffRows between original and revised texts
218239 */
219240 public List <DiffRow > generateDiffRows (final List <String > original , Patch <String > patch ) throws DiffException {
220- // normalize the lines (expand tabs, escape html entities)
221- //List<String> original = originalText;
222- //List<String> revised = StringUtils.normalize(revisedText);
223-
224- // wrap to the column width
225- // TODO: we want to process original text und not wrapped text
226- //original = StringUtils.wrapText(original, this.columnWidth);
227- //revised = StringUtils.wrapText(revised, this.columnWidth);
228241 List <DiffRow > diffRows = new ArrayList <>();
229242 int endPos = 0 ;
230243 final List <Delta <String >> deltaList = patch .getDeltas ();
@@ -233,15 +246,6 @@ public List<DiffRow> generateDiffRows(final List<String> original, Patch<String>
233246 Chunk <String > orig = delta .getOriginal ();
234247 Chunk <String > rev = delta .getRevised ();
235248
236- // We should normalize and wrap lines in deltas too.
237- // TODO: not in Deltas
238- //orig.setLines(StringUtils.normalize((List<String>) orig.getLines()));
239- //rev.setLines(StringUtils.normalize((List<String>) rev.getLines()));
240-
241- //TODO: no we shouldnt: Deltas should not be used for display purposes
242- //orig.setLines(StringUtils.wrapText((List<String>) orig.getLines(), this.columnWidth));
243- //rev.setLines(StringUtils.wrapText((List<String>) rev.getLines(), this.columnWidth));
244- // catch the equal prefix for each chunk
245249 for (String line : original .subList (endPos , orig .getPosition ())) {
246250 diffRows .add (buildDiffRow (Tag .EQUAL , line , line ));
247251 }
@@ -265,23 +269,12 @@ public List<DiffRow> generateDiffRows(final List<String> original, Patch<String>
265269 }
266270
267271 if (showInlineDiffs ) {
268- diffRows .addAll (generateInlineDiffs (delta , false ));
272+ diffRows .addAll (generateInlineDiffs (delta ));
269273 } else {
270- if (orig .size () == rev .size ()) {
271- for (int j = 0 ; j < orig .size (); j ++) {
272- diffRows .add (buildDiffRow (Tag .CHANGE , (String ) orig .getLines ().get (j ),
273- (String ) rev .getLines ().get (j )));
274- }
275- } else if (orig .size () > rev .size ()) {
276- for (int j = 0 ; j < orig .size (); j ++) {
277- diffRows .add (buildDiffRow (Tag .CHANGE , (String ) orig .getLines ().get (j ), rev
278- .getLines ().size () > j ? (String ) rev .getLines ().get (j ) : "" ));
279- }
280- } else {
281- for (int j = 0 ; j < rev .size (); j ++) {
282- diffRows .add (buildDiffRow (Tag .CHANGE , orig .getLines ().size () > j ? (String ) orig
283- .getLines ().get (j ) : "" , (String ) rev .getLines ().get (j )));
284- }
274+ for (int j = 0 ; j < Math .max (orig .size (), rev .size ()); j ++) {
275+ diffRows .add (buildDiffRow (Tag .CHANGE ,
276+ orig .getLines ().size () > j ? orig .getLines ().get (j ) : "" ,
277+ rev .getLines ().size () > j ? rev .getLines ().get (j ) : "" ));
285278 }
286279 }
287280 endPos = orig .last () + 1 ;
@@ -299,60 +292,73 @@ public List<DiffRow> generateDiffRows(final List<String> original, Patch<String>
299292 *
300293 * @param delta the given delta
301294 */
302- private List <DiffRow > generateInlineDiffs (Delta <String > delta , boolean mergeToTarget ) throws DiffException {
303- if (delta .getType ()!=Delta .DeltaType .CHANGE )
304- throw new IllegalArgumentException ("only for change deltas allowed" );
305- // List<String> orig = delta.getOriginal().getLines();
306- // List<String> rev = delta.getRevised().getLines();
307- // LinkedList<String> origList = new LinkedList<>();
308- // for (Character character : String.join("\n", orig).toCharArray()) {
309- // origList.add(character.toString());
310- // }
311- // LinkedList<String> revList = new LinkedList<>();
312- // for (Character character : String.join("\n", rev).toCharArray()) {
313- // revList.add(character.toString());
314- // }
315- // List<Delta<String>> inlineDeltas = DiffUtils.diff(origList, revList).getDeltas();
316- Patch <String > patch = DiffUtils .diffInline (String .join ("\n " , delta .getOriginal ().getLines ()), String .join ("\n " , delta .getRevised ().getLines ()));
317- if (patch .getDeltas ().size () < 3 ) {
318- List <Delta <String >> deltas = new ArrayList <>(patch .getDeltas ());
319- Collections .reverse (deltas );
320-
321- for (Delta <String > inlineDelta : deltas ) {
322- System .out .println (inlineDelta );
295+ private List <DiffRow > generateInlineDiffs (Delta <String > delta ) throws DiffException {
296+ List <String > orig = StringUtils .normalize (delta .getOriginal ().getLines ());
297+ List <String > rev = StringUtils .normalize (delta .getRevised ().getLines ());
298+ LinkedList <String > origList = new LinkedList <>();
299+ for (Character character : String .join ("\n " , orig ).toCharArray ()) {
300+ origList .add (character .toString ());
301+ }
302+ LinkedList <String > revList = new LinkedList <>();
303+ for (Character character : String .join ("\n " , rev ).toCharArray ()) {
304+ revList .add (character .toString ());
305+ }
306+ List <Delta <String >> inlineDeltas = DiffUtils .diff (origList , revList ).getDeltas ();
307+
308+ Collections .reverse (inlineDeltas );
309+ for (Delta <String > inlineDelta : inlineDeltas ) {
310+ Chunk <String > inlineOrig = inlineDelta .getOriginal ();
311+ Chunk <String > inlineRev = inlineDelta .getRevised ();
312+ if (inlineDelta instanceof DeleteDelta ) {
313+ wrapInTag (origList , inlineOrig .getPosition (), inlineOrig
314+ .getPosition ()
315+ + inlineOrig .size () + 1 , this .inlineOldTag , this .inlineOldCssClass );
316+ } else if (inlineDelta instanceof InsertDelta ) {
317+ if (mergeInline ) {
318+ origList .addAll (inlineOrig .getPosition (),
319+ revList .subList (inlineRev .getPosition (), inlineRev .getPosition ()
320+ + inlineRev .size ()));
321+ wrapInTag (origList , inlineOrig .getPosition (), inlineOrig .getPosition ()
322+ + inlineRev .size () + 1 , this .inlineNewTag , this .inlineNewCssClass );
323+ } else {
324+ wrapInTag (revList , inlineRev .getPosition (), inlineRev .getPosition ()
325+ + inlineRev .size () + 1 , this .inlineNewTag , this .inlineNewCssClass );
326+ }
327+ } else if (inlineDelta instanceof ChangeDelta ) {
328+ if (mergeInline ) {
329+ origList .addAll (inlineOrig .getPosition (),
330+ revList .subList (inlineRev .getPosition (), inlineRev .getPosition ()
331+ + inlineRev .size ()));
332+ wrapInTag (origList , inlineOrig .getPosition (), inlineOrig .getPosition ()
333+ + inlineRev .size () + 1 , this .inlineNewTag , this .inlineNewCssClass );
334+ } else {
335+ wrapInTag (revList , inlineRev .getPosition (), inlineRev .getPosition ()
336+ + inlineRev .size () + 1 , this .inlineNewTag , this .inlineNewCssClass );
337+ }
338+ wrapInTag (origList , inlineOrig .getPosition (), inlineOrig
339+ .getPosition ()
340+ + inlineOrig .size () + 1 , this .inlineOldTag , this .inlineOldCssClass );
323341 }
324-
325-
326- return Collections .EMPTY_LIST ;
327- // Collections.reverse(inlineDeltas);
328- // for (Delta<String> inlineDelta : inlineDeltas) {
329- // Chunk<String> inlineOrig = inlineDelta.getOriginal();
330- // Chunk<String> inlineRev = inlineDelta.getRevised();
331- // if (inlineDelta instanceof DeleteDelta) {
332- // origList = wrapInTag(origList, inlineOrig.getPosition(), inlineOrig
333- // .getPosition()
334- // + inlineOrig.size() + 1, this.inlineOldTag, this.inlineOldCssClass);
335- // } else if (inlineDelta instanceof InsertDelta) {
336- // revList = wrapInTag(revList, inlineRev.getPosition(), inlineRev.getPosition()
337- // + inlineRev.size() + 1, this.inlineNewTag, this.inlineNewCssClass);
338- // } else if (inlineDelta instanceof ChangeDelta) {
339- // origList = wrapInTag(origList, inlineOrig.getPosition(), inlineOrig
340- // .getPosition()
341- // + inlineOrig.size() + 1, this.inlineOldTag, this.inlineOldCssClass);
342- // revList = wrapInTag(revList, inlineRev.getPosition(), inlineRev.getPosition()
343- // + inlineRev.size() + 1, this.inlineNewTag, this.inlineNewCssClass);
344- // }
345- // }
346- // StringBuilder origResult = new StringBuilder(), revResult = new StringBuilder();
347- // for (String character : origList) {
348- // origResult.append(character);
349- // }
350- // for (String character : revList) {
351- // revResult.append(character);
352- // }
353- // delta.getOriginal().setLines(Arrays.asList(origResult.toString().split("\n")));
354- // delta.getRevised().setLines(Arrays.asList(revResult.toString().split("\n")));
355- } else return Collections .emptyList ();
342+ }
343+ StringBuilder origResult = new StringBuilder ();
344+ StringBuilder revResult = new StringBuilder ();
345+ for (String character : origList ) {
346+ origResult .append (character );
347+ }
348+ for (String character : revList ) {
349+ revResult .append (character );
350+ }
351+
352+ List <String > original = Arrays .asList (origResult .toString ().split ("\n " ));
353+ List <String > revised = Arrays .asList (revResult .toString ().split ("\n " ));
354+ List <DiffRow > diffRows = new ArrayList <>();
355+ for (int j = 0 ; j < Math .max (original .size (), revised .size ()); j ++) {
356+ diffRows .
357+ add (buildDiffRowWithoutNormalizing (Tag .CHANGE ,
358+ original .size () > j ? original .get (j ) : "" ,
359+ revised .size () > j ? revised .get (j ) : "" ));
360+ }
361+ return diffRows ;
356362 }
357363
358364 /**
@@ -364,59 +370,17 @@ private List<DiffRow> generateInlineDiffs(Delta<String> delta, boolean mergeToTa
364370 * @param tag the tag name without angle brackets, just a word
365371 * @param cssClass the optional css class
366372 */
367- public static LinkedList < String > wrapInTag (LinkedList <String > sequence , int startPosition ,
373+ public static void wrapInTag (LinkedList <String > sequence , int startPosition ,
368374 int endPosition , String tag , String cssClass ) {
369- LinkedList <String > result = (LinkedList <String >) sequence .clone ();
370- StringBuilder tagBuilder = new StringBuilder ();
371- tagBuilder .append ("<" );
372- tagBuilder .append (tag );
373- if (cssClass != null ) {
374- tagBuilder .append (" class=\" " );
375- tagBuilder .append (cssClass );
376- tagBuilder .append ("\" " );
377- }
378- tagBuilder .append (">" );
379- String startTag = tagBuilder .toString ();
380-
381- tagBuilder .delete (0 , tagBuilder .length ());
382-
383- tagBuilder .append ("</" );
384- tagBuilder .append (tag );
385- tagBuilder .append (">" );
386- String endTag = tagBuilder .toString ();
387-
388- result .add (startPosition , startTag );
389- result .add (endPosition , endTag );
390- return result ;
375+ sequence .add (startPosition , createOpenTag (tag , cssClass ));
376+ sequence .add (endPosition , createCloseTag (tag ));
391377 }
392378
393- /**
394- * Wrap the given line with the given tag
395- *
396- * @param line the given line
397- * @param tag the tag name without angle brackets, just a word
398- * @param cssClass the optional css class
399- * @return the wrapped string
400- */
401- public static String wrapInTag (String line , String tag , String cssClass ) {
402- StringBuilder tagBuilder = new StringBuilder ();
403- tagBuilder .append ("<" );
404- tagBuilder .append (tag );
405- if (cssClass != null ) {
406- tagBuilder .append (" class=\" " );
407- tagBuilder .append (cssClass );
408- tagBuilder .append ("\" " );
409- }
410- tagBuilder .append (">" );
411- String startTag = tagBuilder .toString ();
412-
413- tagBuilder .delete (0 , tagBuilder .length ());
414-
415- tagBuilder .append ("</" );
416- tagBuilder .append (tag );
417- tagBuilder .append (">" );
418- String endTag = tagBuilder .toString ();
379+ private static String createCloseTag (String tag ) {
380+ return "</" + tag + ">" ;
381+ }
419382
420- return startTag + line + endTag ;
383+ private static String createOpenTag (String tag , String cssClass ) {
384+ return "<" + tag + (cssClass != null ? " class=\" " + cssClass + "\" " : "" ) + ">" ;
421385 }
422386}
0 commit comments