* DiffRowGenerator generator = new DiffRowGenerator.Builder().showInlineDiffs(true).
* ignoreWhiteSpaces(true).columnWidth(100).build();
*
- *
+ *
* @author Dmitry Naumenko
*/
public class DiffRowGenerator {
@@ -48,7 +49,8 @@ public class DiffRowGenerator {
private final String InlineOldCssClass;
private final String InlineNewCssClass;
private final int columnWidth;
-
+ private final Equalizer equalizer;
+
/**
* This class used for building the DiffRowGenerator.
* @author dmitry
@@ -56,24 +58,24 @@ public class DiffRowGenerator {
*/
public static class Builder {
private boolean showInlineDiffs = false;
- private boolean ignoreWhiteSpaces = true;
- private boolean ignoreBlankLines = true;
+ private boolean ignoreWhiteSpaces = false;
+ private boolean ignoreBlankLines = false;
private String InlineOldTag = "span";
private String InlineNewTag = "span";
private String InlineOldCssClass = "editOldInline";
private String InlineNewCssClass = "editNewInline";
private int columnWidth = 80;
-
+
/**
* Show inline diffs in generating diff rows or not.
* @param val the value to set. Default: false.
- * @return builder with configured showInlineDiff parameter
+ * @return builder with configured showInlineDiff parameter
*/
public Builder showInlineDiffs(boolean val) {
showInlineDiffs = val;
return this;
}
-
+
/**
* Ignore white spaces in generating diff rows or not.
* @param val the value to set. Default: true.
@@ -83,7 +85,7 @@ public class DiffRowGenerator {
ignoreWhiteSpaces = val;
return this;
}
-
+
/**
* Ignore blank lines in generating diff rows or not.
* @param val the value to set. Default: true.
@@ -93,7 +95,7 @@ public class DiffRowGenerator {
ignoreBlankLines = val;
return this;
}
-
+
/**
* Set the tag used for displaying changes in the original text.
* @param tag the tag to set. Without angle brackets. Default: span.
@@ -103,7 +105,7 @@ public class DiffRowGenerator {
InlineOldTag = tag;
return this;
}
-
+
/**
* Set the tag used for displaying changes in the revised text.
* @param tag the tag to set. Without angle brackets. Default: span.
@@ -113,7 +115,7 @@ public class DiffRowGenerator {
InlineNewTag = tag;
return this;
}
-
+
/**
* Set the css class used for displaying changes in the original text.
* @param cssClass the tag to set. Without any quotes, just word. Default: editOldInline.
@@ -123,7 +125,7 @@ public class DiffRowGenerator {
InlineOldCssClass = cssClass;
return this;
}
-
+
/**
* Set the css class used for displaying changes in the revised text.
* @param cssClass the tag to set. Without any quotes, just word. Default: editNewInline.
@@ -133,7 +135,7 @@ public class DiffRowGenerator {
InlineNewCssClass = cssClass;
return this;
}
-
+
/**
* Set the column with of generated lines of original and revised texts.
* @param width the width to set. Making it < 0 doesn't have any sense. Default 80.
@@ -145,7 +147,7 @@ public class DiffRowGenerator {
}
return this;
}
-
+
/**
* Build the DiffRowGenerator. If some parameters is not set, the default values are used.
* @return the customized DiffRowGenerator
@@ -154,7 +156,7 @@ public class DiffRowGenerator {
return new DiffRowGenerator(this);
}
}
-
+
private DiffRowGenerator(Builder builder) {
showInlineDiffs = builder.showInlineDiffs;
ignoreWhiteSpaces = builder.ignoreWhiteSpaces; //
@@ -164,27 +166,47 @@ public class DiffRowGenerator {
InlineOldCssClass = builder.InlineOldCssClass;
InlineNewCssClass = builder.InlineNewCssClass;
columnWidth = builder.columnWidth; //
+ equalizer = new Equalizer() {
+ public boolean equals(Object original, Object revised) {
+ if (ignoreWhiteSpaces) {
+ original = ((String)original).trim().replaceAll("\\s+", " ");
+ revised = ((String)revised).trim().replaceAll("\\s+", " ");
+ }
+ return original.equals(revised);
+ }
+ };
}
-
+
/**
* Get the DiffRows describing the difference between original and revised texts using the
* given patch. Useful for displaying side-by-side diff.
- *
+ *
* @param original the original text
- * @param revised the revised text
+ * @param revised the revised text
* @return the DiffRows between original and revised texts
*/
public ListSee the paper at * http://www.cs.arizona.edu/people/gene/PAPERS/diff.ps
* * @author Juanco Anez */ public class MyersDiff implements DiffAlgorithm { + private static final Equalizer DEFAULT_EQUALIZER = new Equalizer() { + public boolean equals(Object original, Object revised) { + return original.equals(revised); + } + }; + + private Equalizer equalizer = DEFAULT_EQUALIZER; + + /** * Constructs an instance of the Myers differencing algorithm. */ public MyersDiff() { } - + + public MyersDiff(Equalizer equalizer) { + this.equalizer = equalizer; + } + /** * {@inheritDoc} - * + * * Return empty diff if get the error while procession the difference. */ public Patch diff(List> original, List> revised) { return diff(original.toArray(), revised.toArray()); } - + /** * {@inheritDoc} - * + * * Return empty diff if get the error while procession the difference. */ public Patch diff(Object[] orig, Object[] rev) { @@ -102,7 +115,7 @@ public class MyersDiff implements DiffAlgorithm { } return new Patch(); } - + /** * Computes the minimum diffpath that expresses de differences * between the original and revised sequences, according @@ -113,22 +126,22 @@ public class MyersDiff implements DiffAlgorithm { * @return A minimum {@link PathNode Path} accross the differences graph. * @throws DifferentiationFailedException if a diff path could not be found. */ - public static PathNode buildPath(Object[] orig, Object[] rev) + public PathNode buildPath(Object[] orig, Object[] rev) throws DifferentiationFailedException { if (orig == null) throw new IllegalArgumentException("original sequence is null"); if (rev == null) throw new IllegalArgumentException("revised sequence is null"); - + // these are local constants final int N = orig.length; final int M = rev.length; - + final int MAX = N + M + 1; final int size = 1 + 2 * MAX; final int middle = size / 2; final PathNode diagonal[] = new PathNode[size]; - + diagonal[middle + 1] = new Snake(0, -1, null); for (int d = 0; d < MAX; d++) { for (int k = -d; k <= d; k += 2) { @@ -136,7 +149,7 @@ public class MyersDiff implements DiffAlgorithm { final int kplus = kmiddle + 1; final int kminus = kmiddle - 1; PathNode prev = null; - + int i; if ((k == -d) || (k != d && diagonal[kminus].i < diagonal[kplus].i)) { i = diagonal[kplus].i; @@ -145,36 +158,40 @@ public class MyersDiff implements DiffAlgorithm { i = diagonal[kminus].i + 1; prev = diagonal[kminus]; } - + diagonal[kminus] = null; // no longer used - + int j = i - k; - + PathNode node = new DiffNode(i, j, prev); - + // orig and rev are zero-based // but the algorithm is one-based // that's why there's no +1 when indexing the sequences - while (i < N && j < M && orig[i].equals(rev[j])) { + while (i < N && j < M && equals(orig[i], rev[j])) { i++; j++; } if (i > node.i) node = new Snake(i, j, node); - + diagonal[kmiddle] = node; - + if (i >= N && j >= M) { return diagonal[kmiddle]; } } diagonal[middle + d - 1] = null; - + } // According to Myers, this cannot happen throw new DifferentiationFailedException("could not find a diff path"); } - + + private boolean equals(Object orig, Object rev) { + return equalizer.equals(orig, rev); + } + /** * Constructs a {@link Patch} from a difference path. * @@ -185,14 +202,14 @@ public class MyersDiff implements DiffAlgorithm { * @throws DifferentiationFailedException if a {@link Patch} could * not be built from the given path. */ - public static Patch buildRevision(PathNode path, Object[] orig, Object[] rev) { + public Patch buildRevision(PathNode path, Object[] orig, Object[] rev) { if (path == null) throw new IllegalArgumentException("path is null"); if (orig == null) throw new IllegalArgumentException("original sequence is null"); if (rev == null) throw new IllegalArgumentException("revised sequence is null"); - + Patch patch = new Patch(); if (path.isSnake()) path = path.prev; @@ -201,11 +218,11 @@ public class MyersDiff implements DiffAlgorithm { throw new IllegalStateException("bad diffpath: found snake when looking for diff"); int i = path.i; int j = path.j; - + path = path.prev; int ianchor = path.i; int janchor = path.j; - + Chunk original = new Chunk(ianchor, copyOfRange(orig, ianchor, i)); Chunk revised = new Chunk(janchor, copyOfRange(rev, janchor, j)); Delta delta = null; @@ -216,23 +233,23 @@ public class MyersDiff implements DiffAlgorithm { } else { delta = new ChangeDelta(original, revised); } - + patch.addDelta(delta); if (path.isSnake()) path = path.prev; } return patch; } - + /** * Copied here from JDK 1.6 */ - + @SuppressWarnings("unchecked") public static