New version which was lost after removing repo.

This commit is contained in:
dm.naumenko@gmail.com
2009-10-04 08:49:25 +00:00
parent 483cc2ee69
commit d131d94817
16 changed files with 1101 additions and 98 deletions

View File

@@ -1,3 +1,21 @@
/*
Copyright 2009 Dmitry Naumenko (dm.naumenko@gmail.com)
This file is part of Java Diff Utills Library.
Java Diff Utills Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Java Diff Utills Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Java Diff Utills Library. If not, see <http://www.gnu.org/licenses/>.
*/
package difflib;
import java.util.List;
@@ -18,12 +36,14 @@ public class ChangeDelta extends Delta {
/**
* {@inheritDoc}
* @throws PatchFailedException
*/
@Override
public void applyTo(List<Object> target) {
public void applyTo(List<Object> target) throws PatchFailedException {
verify(target);
int position = getOriginal().getPosition();
int originalSize = getOriginal().getSize();
for (int i = 0; i < originalSize; i++) {
int size = getOriginal().getSize();
for (int i = 0; i < size; i++) {
target.remove(position);
}
int i = 0;
@@ -33,4 +53,32 @@ public class ChangeDelta extends Delta {
}
}
/**
* {@inheritDoc}
*/
@Override
public void restore(List<Object> target) {
int position = getRevised().getPosition();
int size = getRevised().getSize();
for (int i = 0; i < size; i++) {
target.remove(position);
}
int i = 0;
for (Object line: getOriginal().getLines()) {
target.add(position + i, line);
i++;
}
}
/**
* {@inheritDoc}
*/
public void verify(List<?> target) throws PatchFailedException {
getOriginal().verify(target);
if (getOriginal().getPosition() > target.size()) {
throw new PatchFailedException("Incorrect patch for delta: " +
"delta original position > target size");
}
}
}

View File

@@ -1,3 +1,21 @@
/*
Copyright 2009 Dmitry Naumenko (dm.naumenko@gmail.com)
This file is part of Java Diff Utills Library.
Java Diff Utills Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Java Diff Utills Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Java Diff Utills Library. If not, see <http://www.gnu.org/licenses/>.
*/
package difflib;
import java.util.*;
@@ -46,6 +64,22 @@ public class Chunk {
this.lines = Arrays.asList(lines);
}
/**
* Verifies that this chunk's saved text matches the corresponding
* text in the given sequence.
* @param target the sequence to verify against.
*/
public void verify(List<?> target) throws PatchFailedException{
if (last() > target.size()) {
throw new PatchFailedException("Incorrect Chunk: the position of chunk > target size");
}
for (int i = 0; i < size; i++) {
if (!target.get(position + i).equals(lines.get(i))) {
throw new PatchFailedException("Incorrect Chunk: the chunk content doesn't match the target");
}
}
}
/**
* @return the start position of chunk in the text
*/
@@ -84,6 +118,13 @@ public class Chunk {
public void setLines(List<?> lines) {
this.lines = lines;
}
/**
* Returns the index of the last line of the chunk.
*/
public int last(){
return getPosition() + getSize() - 1;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()

View File

@@ -1,3 +1,21 @@
/*
Copyright 2009 Dmitry Naumenko (dm.naumenko@gmail.com)
This file is part of Java Diff Utills Library.
Java Diff Utills Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Java Diff Utills Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Java Diff Utills Library. If not, see <http://www.gnu.org/licenses/>.
*/
package difflib;
import java.util.List;
@@ -18,9 +36,11 @@ public class DeleteDelta extends Delta {
/**
* {@inheritDoc}
* @throws PatchFailedException
*/
@Override
public void applyTo(List<Object> target) {
public void applyTo(List<Object> target) throws PatchFailedException {
verify(target);
int position = getOriginal().getPosition();
int size = getOriginal().getSize();
for (int i = 0; i < size; i++) {
@@ -28,4 +48,26 @@ public class DeleteDelta extends Delta {
}
}
/**
* {@inheritDoc}
*/
@Override
public void restore(List<Object> target) {
int position = this.getRevised().getPosition();
List<?> lines = this.getOriginal().getLines();
for (int i = 0; i < lines.size(); i++) {
target.add(position + i, lines.get(i));
}
}
@Override
public void verify(List<?> target) throws PatchFailedException {
getOriginal().verify(target);
}
@Override
public String toString() {
return "[DeleteDelta, position: " + getOriginal().getPosition() + ", lines: " +
getOriginal().getLines() + "]";
}
}

View File

@@ -1,3 +1,21 @@
/*
Copyright 2009 Dmitry Naumenko (dm.naumenko@gmail.com)
This file is part of Java Diff Utills Library.
Java Diff Utills Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Java Diff Utills Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Java Diff Utills Library. If not, see <http://www.gnu.org/licenses/>.
*/
package difflib;
import java.util.*;
@@ -22,12 +40,27 @@ public abstract class Delta {
this.revised = revised;
}
/**
* Verifies that this delta can be used to patch the given text.
* @param target the text to patch.
* @throws PatchFailedException if the patch cannot be applied.
*/
public abstract void verify(List<?> target) throws PatchFailedException;
/**
* Applies this delta as the patch for a given target
*
* @param target the given target
* @param target the given target
* @throws PatchFailedException
*/
public abstract void applyTo(List<Object> target);
public abstract void applyTo(List<Object> target) throws PatchFailedException;
/**
* Cancel this delta for a given revised text. The action is opposite to patch.
*
* @param target the given revised text
*/
public abstract void restore(List<Object> target);
/**
* @return the Chunk describing the original text
@@ -54,4 +87,44 @@ public abstract class Delta {
public void setRevised(Chunk revised) {
this.revised = revised;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((original == null) ? 0 : original.hashCode());
result = prime * result + ((revised == null) ? 0 : revised.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Delta other = (Delta) obj;
if (original == null) {
if (other.original != null)
return false;
} else if (!original.equals(other.original))
return false;
if (revised == null) {
if (other.revised != null)
return false;
} else if (!revised.equals(other.revised))
return false;
return true;
}
}

View File

@@ -1,3 +1,21 @@
/*
Copyright 2009 Dmitry Naumenko (dm.naumenko@gmail.com)
This file is part of Java Diff Utills Library.
Java Diff Utills Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Java Diff Utills Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Java Diff Utills Library. If not, see <http://www.gnu.org/licenses/>.
*/
package difflib;
import java.util.*;

View File

@@ -0,0 +1,37 @@
/*
Copyright 2009 Dmitry Naumenko (dm.naumenko@gmail.com)
This file is part of Java Diff Utills Library.
Java Diff Utills Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Java Diff Utills Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Java Diff Utills Library. If not, see <http://www.gnu.org/licenses/>.
*/
package difflib;
/**
* Base class for all exceptions emanating from this package.
*
* @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a>
*/
public class DiffException extends Exception {
private static final long serialVersionUID = 1L;
public DiffException() {
}
public DiffException(String msg) {
super(msg);
}
}

View File

@@ -1,3 +1,21 @@
/*
Copyright 2009 Dmitry Naumenko (dm.naumenko@gmail.com)
This file is part of Java Diff Utills Library.
Java Diff Utills Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Java Diff Utills Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Java Diff Utills Library. If not, see <http://www.gnu.org/licenses/>.
*/
package difflib;
/**
@@ -11,8 +29,14 @@ public class DiffRow {
private String oldLine;
private String newLine;
public DiffRow(Tag tag, String oldLine, String newLine) {
this.tag = tag;
this.oldLine = oldLine;
this.newLine = newLine;
}
public enum Tag {
INSERT, DELETE, CHANGE
INSERT, DELETE, CHANGE, EQUAL
}
/**
@@ -53,4 +77,50 @@ public class DiffRow {
public void setNewLine(String newLine) {
this.newLine = newLine;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((newLine == null) ? 0 : newLine.hashCode());
result = prime * result + ((oldLine == null) ? 0 : oldLine.hashCode());
result = prime * result + ((tag == null) ? 0 : tag.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DiffRow other = (DiffRow) obj;
if (newLine == null) {
if (other.newLine != null)
return false;
} else if (!newLine.equals(other.newLine))
return false;
if (oldLine == null) {
if (other.oldLine != null)
return false;
} else if (!oldLine.equals(other.oldLine))
return false;
if (tag == null) {
if (other.tag != null)
return false;
} else if (!tag.equals(other.tag))
return false;
return true;
}
public String toString() {
return "[" + this.tag + "," + this.oldLine + "," + this.newLine + "]";
}
}

View File

@@ -0,0 +1,405 @@
/*
Copyright 2009 Dmitry Naumenko (dm.naumenko@gmail.com)
This file is part of Java Diff Utills Library.
Java Diff Utills Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Java Diff Utills Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Java Diff Utills Library. If not, see <http://www.gnu.org/licenses/>.
*/
package difflib;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import difflib.DiffRow.Tag;
/**
* This class for generating DiffRows for side-by-sidy view.
* You can customize the way of generating. For example, show inline diffs on not, ignoring
* white spaces or/and blank lines and so on. All parameters for generating are optional. If you do
* not specify them, the class will use the default values.
*
* These values are:
* showInlineDiffs = false;
* ignoreWhiteSpaces = true;
* ignoreBlankLines = true;
* ...
*
* For instantiating the DiffRowGenerator you should use the its builder. Like in example
* <code>
* DiffRowGenerator generator = new DiffRowGenerator.Builder().showInlineDiffs(true).
* ignoreWhiteSpaces(true).columnWidth(100).build();
* </code>
*
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
*/
public class DiffRowGenerator {
private final boolean showInlineDiffs;
private final boolean ignoreWhiteSpaces;
private final boolean ignoreBlankLines;
private final String InlineOldTag;
private final String InlineNewTag;
private final String InlineOldCssClass;
private final String InlineNewCssClass;
private final int columnWidth;
/**
* This class used for building the DiffRowGenerator.
* @author dmitry
*
*/
public static class Builder {
private boolean showInlineDiffs = false;
private boolean ignoreWhiteSpaces = true;
private boolean ignoreBlankLines = true;
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
*/
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.
* @return builder with configured ignoreWhiteSpaces parameter
*/
public Builder ignoreWhiteSpaces(boolean val) {
ignoreWhiteSpaces = val;
return this;
}
/**
* Ignore blank lines in generating diff rows or not.
* @param val the value to set. Default: true.
* @return builder with configured ignoreBlankLines parameter
*/
public Builder ignoreBlankLines(boolean val) {
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.
* @return builder with configured ignoreBlankLines parameter
*/
public Builder InlineOldTag(String tag) {
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.
* @return builder with configured ignoreBlankLines parameter
*/
public Builder InlineNewTag(String tag) {
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.
* @return builder with configured ignoreBlankLines parameter
*/
public Builder InlineOldCssClass(String cssClass) {
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.
* @return builder with configured ignoreBlankLines parameter
*/
public Builder InlineNewCssClass(String cssClass) {
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.
* @return builder with configured ignoreBlankLines parameter
*/
public Builder columnWidth(int width) {
if (width > 0) {
columnWidth = width;
}
return this;
}
/**
* Build the DiffRowGenerator. If some parameters is not set, the default values are used.
* @return the customized DiffRowGenerator
*/
public DiffRowGenerator build() {
return new DiffRowGenerator(this);
}
}
private DiffRowGenerator(Builder builder) {
showInlineDiffs = builder.showInlineDiffs;
ignoreWhiteSpaces = builder.ignoreWhiteSpaces; //
ignoreBlankLines = builder.ignoreBlankLines; //
InlineOldTag = builder.InlineOldTag;
InlineNewTag = builder.InlineNewTag;
InlineOldCssClass = builder.InlineOldCssClass;
InlineNewCssClass = builder.InlineNewCssClass;
columnWidth = builder.columnWidth; //
}
/**
* 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
* @return the DiffRows between original and revised texts
*/
public List<DiffRow> generateDiffRows(List<String> original, List<String> revised) {
return generateDiffRows(original, revised, DiffUtils.diff(original, revised));
}
/**
* Generates 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 patch the given patch
* @return the DiffRows between original and revised texts
*/
@SuppressWarnings("unchecked")
public List<DiffRow> generateDiffRows(List<String> original, List<String> revised, Patch patch) {
// normalize the lines (expand tabs, escape html entities)
original = StringUtills.normalize((List<String>)original);
revised = StringUtills.normalize((List<String>)revised);
// wrap to the column width
original = StringUtills.wrapText((List<String>)original, this.columnWidth);
revised = StringUtills.wrapText((List<String>)revised, this.columnWidth);
List<DiffRow> diffRows = new ArrayList<DiffRow>();
int endPos = 0;
for (int i = 0; i < patch.getDeltas().size(); i++) {
Delta delta = patch.getDelta(i);
Chunk orig = delta.getOriginal();
Chunk rev = delta.getRevised();
// We should normalize and wrap lines in deltas too.
orig.setLines(StringUtills.normalize((List<String>)orig.getLines()));
rev.setLines(StringUtills.normalize((List<String>)rev.getLines()));
orig.setLines(StringUtills.wrapText((List<String>)orig.getLines(), this.columnWidth));
rev.setLines(StringUtills.wrapText((List<String>)rev.getLines(), this.columnWidth));
// catch the equal prefix for each chunk
for (String line: original.subList(endPos, orig.getPosition())) {
diffRows.add(new DiffRow(Tag.EQUAL, line, line));
}
// Inserted DiffRow
if (delta.getClass().equals(InsertDelta.class)) {
endPos = orig.last() + 1;
for (String line: (List<String>)rev.getLines()) {
diffRows.add(new DiffRow(Tag.INSERT, "", line));
}
continue;
}
// Deleted DiffRow
if (delta.getClass().equals(DeleteDelta.class)) {
endPos = orig.last() + 1;
for (String line: (List<String>)orig.getLines()) {
diffRows.add(new DiffRow(Tag.DELETE, line, ""));
}
continue;
}
if (showInlineDiffs) {
addInlineDiffs(delta);
}
// the changed size is match
if (orig.getSize() == rev.getSize()) {
for (int j = 0; j < orig.getSize(); j++) {
diffRows.add(new DiffRow(Tag.CHANGE, (String)orig.getLines().get(j),
(String)rev.getLines().get(j)));
}
} else if (orig.getSize() > rev.getSize()) {
for (int j = 0; j < orig.getSize(); j++) {
diffRows.add(new DiffRow(Tag.CHANGE, (String)orig.getLines().get(j),
rev.getLines().size() > j ? (String)rev.getLines().get(j) : ""));
}
} else {
for (int j = 0; j < rev.getSize(); j++) {
diffRows.add(new DiffRow(Tag.CHANGE, orig.getLines().size() > j ?
(String)orig.getLines().get(j) : "", (String)rev.getLines().get(j)));
}
}
endPos = orig.last() + 1;
}
// Copy the final matching chunk if any.
for (String line: original.subList(endPos, original.size())) {
diffRows.add(new DiffRow(Tag.EQUAL, line, line));
}
return diffRows;
}
/**
* Add the inline diffs for given delta
* @param delta the given delta
*/
@SuppressWarnings("unchecked")
private void addInlineDiffs(Delta delta) {
List<String> orig = (List<String>)delta.getOriginal().getLines();
List<String> rev = (List<String>)delta.getRevised().getLines();
LinkedList<String> origList = new LinkedList<String>();
for (Character character: join(orig, "\n").toCharArray()) {
origList.add(character.toString());
}
LinkedList<String> revList = new LinkedList<String>();
for (Character character: join(rev, "\n").toCharArray()) {
revList.add(character.toString());
}
List<Delta> inlineDeltas = DiffUtils.diff(origList, revList).getDeltas();
if (inlineDeltas.size() < 3) {
Collections.reverse(inlineDeltas);
for (Delta inlineDelta: inlineDeltas) {
Chunk inlineOrig = inlineDelta.getOriginal();
Chunk inlineRev = inlineDelta.getRevised();
if (inlineDelta.getClass().equals(DeleteDelta.class)) {
origList = wrapInTag(origList, inlineOrig.getPosition(),
inlineOrig.getPosition() + inlineOrig.getSize() + 1,
this.InlineOldTag, this.InlineOldCssClass);
} else if (inlineDelta.getClass().equals(InsertDelta.class)) {
revList = wrapInTag(revList, inlineRev.getPosition(),
inlineRev.getPosition() + inlineRev.getSize() + 1,
this.InlineNewTag, this.InlineNewCssClass);
} else if (inlineDelta.getClass().equals(ChangeDelta.class)) {
origList = wrapInTag(origList, inlineOrig.getPosition(),
inlineOrig.getPosition() + inlineOrig.getSize() + 1,
this.InlineOldTag, this.InlineOldCssClass);
revList = wrapInTag(revList, inlineRev.getPosition(),
inlineRev.getPosition() + inlineRev.getSize() + 1,
this.InlineNewTag, this.InlineNewCssClass);
}
}
StringBuilder origResult = new StringBuilder(), revResult = new StringBuilder();
for (String character: origList) {
origResult.append(character);
}
for (String character: revList) {
revResult.append(character);
}
delta.getOriginal().setLines(Arrays.asList(origResult.toString().split("\n")));
delta.getRevised().setLines(Arrays.asList(revResult.toString().split("\n")));
}
}
/**
* Wrap the elements in the sequence with the given tag
* @param startPosition the position from which tag should start. The counting start from a zero.
* @param endPosition the position before which tag should should be closed.
* @param tag the tag name without angle brackets, just a word
* @param cssClass the optional css class
*/
public static LinkedList<String> wrapInTag(LinkedList<String> sequence, int startPosition, int endPosition, String tag, String cssClass) {
LinkedList<String> result = (LinkedList<String>)sequence.clone();
StringBuilder tagBuilder = new StringBuilder();
tagBuilder.append("<");
tagBuilder.append(tag);
if (cssClass != null) {
tagBuilder.append(" class=\"");
tagBuilder.append(cssClass);
tagBuilder.append("\"");
}
tagBuilder.append(">");
String startTag = tagBuilder.toString();
tagBuilder.delete(0, tagBuilder.length());
tagBuilder.append("</");
tagBuilder.append(tag);
tagBuilder.append(">");
String endTag = tagBuilder.toString();
result.add(startPosition, startTag);
result.add(endPosition, endTag);
return result;
}
/**
* Wrap the given line with the given tag
* @param line the given line
* @param tag the tag name without angle brackets, just a word
* @param cssClass the optional css class
* @return the wrapped string
*/
public static String wrapInTag(String line, String tag, String cssClass) {
StringBuilder tagBuilder = new StringBuilder();
tagBuilder.append("<");
tagBuilder.append(tag);
if (cssClass != null) {
tagBuilder.append(" class=\"");
tagBuilder.append(cssClass);
tagBuilder.append("\"");
}
tagBuilder.append(">");
String startTag = tagBuilder.toString();
tagBuilder.delete(0, tagBuilder.length());
tagBuilder.append("</");
tagBuilder.append(tag);
tagBuilder.append(">");
String endTag = tagBuilder.toString();
return startTag + line + endTag;
}
/**
* The helper method for joining collections
* @param <T>
* @param objs the collection to join
* @param delimiter the delimiter to use
* @return the joined string
*/
private static <T> String join(final Iterable<T> objs, final String delimiter) {
Iterator<T> iter = objs.iterator();
if (!iter.hasNext()) {
return "";
}
StringBuffer buffer = new StringBuffer(String.valueOf(iter.next()));
while (iter.hasNext()) {
buffer.append(delimiter).append(String.valueOf(iter.next()));
}
return buffer.toString();
}
}

View File

@@ -1,3 +1,21 @@
/*
Copyright 2009 Dmitry Naumenko (dm.naumenko@gmail.com)
This file is part of Java Diff Utills Library.
Java Diff Utills Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Java Diff Utills Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Java Diff Utills Library. If not, see <http://www.gnu.org/licenses/>.
*/
package difflib;
import java.util.*;
@@ -10,6 +28,7 @@ import difflib.myers.*;
* Implements the difference and patching engine
*
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
* @version 0.4.1
*/
public class DiffUtils {
private static DiffAlgorithm defaultDiffAlgorithm = new MyersDiff();
@@ -45,8 +64,9 @@ public class DiffUtils {
* @param original the original text
* @param patch the given patch
* @return the revised text
* @throws PatchFailedException if can't apply patch
*/
public static List<?> patch(List<?> original, Patch patch) {
public static List<?> patch(List<?> original, Patch patch) throws PatchFailedException {
return patch.applyTo(original);
}
@@ -57,15 +77,15 @@ public class DiffUtils {
* @param patch the given patch
* @return the original text
*/
public static String unpatch(String revised, Patch patch) {
// TODO: Not-implemented
return null;
public static List<?> unpatch(List<?> revised, Patch patch) {
return patch.restore(revised);
}
/**
* Parse the given text in unified format and creates the list of deltas for it.
*
* @param diff the text in unified format
* @return the patch with deltas.
*/
public static Patch parseUnifiedDiff(List<String> diff) {
boolean inPrelude = true;
@@ -104,15 +124,25 @@ public class DiffUtils {
rawChunk.clear();
}
// Parse the @@ header
old_ln = m.group(1) == null ? 1 : Integer.parseInt(m.group(1));
old_n = m.group(2) == null ? 1 : Integer.parseInt(m.group(2));
new_ln = m.group(3) == null ? 1 : Integer.parseInt(m.group(3));
new_n = m.group(4) == null ? 1 : Integer.parseInt(m.group(4));
old_ln = Integer.parseInt(m.group(1));
old_n = Integer.parseInt(m.group(2));
new_ln = Integer.parseInt(m.group(3));
new_n = Integer.parseInt(m.group(4));
if (old_ln == 0) {
old_ln += 1;
}
if (new_ln == 0) {
new_ln += 1;
}
} else {
tag = line.substring(0, 1);
rest = line.substring(1);
if (tag.equals(" ") || tag.equals("+") || tag.equals("-")) {
rawChunk.add(new Object[] {tag, rest});
if (line.length() > 0) {
tag = line.substring(0, 1);
rest = line.substring(1);
if (tag.equals(" ") || tag.equals("+") || tag.equals("-")) {
rawChunk.add(new Object[] {tag, rest});
}
}
}
}
@@ -141,15 +171,4 @@ public class DiffUtils {
return patch;
}
/**
* Get the DiffRows describing the difference between original and revised texts. Useful for
* displaying side-by-side diff. Computes the Patch before generate the diffs.
*
* @param original the original text
* @param revised the revised text
* @return the DiffRows between original and revised texts
*/
public static List<DiffRow> getDiffRows(List<?> original, List<?> revised) {
return null;
}
}

View File

@@ -1,3 +1,21 @@
/*
Copyright 2009 Dmitry Naumenko (dm.naumenko@gmail.com)
This file is part of Java Diff Utills Library.
Java Diff Utills Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Java Diff Utills Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Java Diff Utills Library. If not, see <http://www.gnu.org/licenses/>.
*/
package difflib;
import java.util.List;
@@ -18,9 +36,11 @@ public class InsertDelta extends Delta {
/**
* {@inheritDoc}
* @throws PatchFailedException
*/
@Override
public void applyTo(List<Object> target) {
public void applyTo(List<Object> target) throws PatchFailedException {
verify(target);
int position = this.getOriginal().getPosition();
List<?> lines = this.getRevised().getLines();
for (int i = 0; i < lines.size(); i++) {
@@ -28,4 +48,30 @@ public class InsertDelta extends Delta {
}
}
/**
* {@inheritDoc}
*/
@Override
public void restore(List<Object> target) {
int position = getRevised().getPosition();
int size = getRevised().getSize();
for (int i = 0; i < size; i++) {
target.remove(position);
}
}
@Override
public void verify(List<?> target) throws PatchFailedException {
if (getOriginal().getPosition() > target.size()) {
throw new PatchFailedException("Incorrect patch for delta: " +
"delta original position > target size");
}
}
@Override
public String toString() {
return "[InsertDelta, position: " + getOriginal().getPosition() + ", lines: " +
getRevised().getLines() + "]";
}
}

View File

@@ -1,3 +1,21 @@
/*
Copyright 2009 Dmitry Naumenko (dm.naumenko@gmail.com)
This file is part of Java Diff Utills Library.
Java Diff Utills Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Java Diff Utills Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Java Diff Utills Library. If not, see <http://www.gnu.org/licenses/>.
*/
package difflib;
import java.util.*;
@@ -9,21 +27,46 @@ import java.util.*;
*/
public class Patch {
private List<Delta> deltas = new LinkedList<Delta>();
private boolean isSorted = false;
public List<?> applyTo(List<?> target) {
/**
* Apply this patch to the given target
* @param target
* @return the patched text
* @throws PatchFailedException if can't apply patch
*/
public List<?> applyTo(List<?> target) throws PatchFailedException {
List<Object> result = new LinkedList<Object>(target);
for (Delta delta: deltas) {
delta.applyTo(result);
}
ListIterator<Delta> it = getDeltas().listIterator(deltas.size());
while (it.hasPrevious()) {
Delta delta = (Delta) it.previous();
delta.applyTo(result);
}
return result;
}
/**
* Restore the text to original. Opposite to applyTo() method.
* @param target the given target
* @return the restored text
*/
public List<?> restore(List<?> target) {
List<Object> result = new LinkedList<Object>(target);
ListIterator<Delta> it = getDeltas().listIterator(deltas.size());
while (it.hasPrevious()) {
Delta delta = (Delta) it.previous();
delta.restore(result);
}
return result;
}
/**
* Add the given delta to this patch
* @param delta the given delta
*/
public void addDelta(Delta delta) {
deltas.add(delta);
isSorted = false;
}
/**
@@ -31,12 +74,38 @@ public class Patch {
*/
public void setDeltas(List<Delta> deltas) {
this.deltas = deltas;
isSorted = false;
}
/**
* Get the list of computed deltas
* @return the deltas
*/
public List<Delta> getDeltas() {
if (!this.isSorted) {
Collections.sort(deltas, new Comparator<Delta>() {
public int compare(Delta d1, Delta d2) {
if (d1.getOriginal().getPosition() > d2.getOriginal().getPosition()) {
return 1;
} else if (d1.getOriginal().getPosition() > d2.getOriginal().getPosition()) {
return -1;
} else {
return 0;
}
}
}
);
isSorted = true;
}
return deltas;
}
/**
* Get the specific delta from patch deltas
* @param index the index of delta
* @return the needed delta
*/
public Delta getDelta(int index) {
return deltas.get(index);
}
}

View File

@@ -0,0 +1,36 @@
/*
Copyright 2009 Dmitry Naumenko (dm.naumenko@gmail.com)
This file is part of Java Diff Utills Library.
Java Diff Utills Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Java Diff Utills Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Java Diff Utills Library. If not, see <http://www.gnu.org/licenses/>.
*/
package difflib;
/**
* Thrown whenever a delta cannot be applied as a patch to a given text.
*
* @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a>
*/
public class PatchFailedException extends DiffException {
private static final long serialVersionUID = 1L;
public PatchFailedException() {
}
public PatchFailedException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,53 @@
package difflib;
import java.util.*;
public class StringUtills {
public static <T> String join(final Iterable<T> objs, final String delimiter) {
Iterator<T> iter = objs.iterator();
if (!iter.hasNext()) {
return "";
}
StringBuffer buffer = new StringBuffer(String.valueOf(iter.next()));
while (iter.hasNext()) {
buffer.append(delimiter).append(String.valueOf(iter.next()));
}
return buffer.toString();
}
public static String expandTabs(String str) {
return str.replace("\t", " ");
}
public static String htmlEntites(String str) {
return str.replace("<", "&lt;").replace(">", "&gt;");
}
public static String normalize(String str) {
return expandTabs(htmlEntites(str));
}
public static List<String> normalize(List<String> list) {
List<String> result = new LinkedList<String>();
for (String line: list) {
result.add(normalize(line));
}
return result;
}
public static List<String> wrapText(List<String> list, int columnWidth) {
List<String> result = new LinkedList<String>();
for (String line: list) {
result.add(wrapText(line, columnWidth));
}
return result;
}
public static String wrapText(String line, int columnWidth) {
if (line.length() > columnWidth) {
return line.subSequence(0, columnWidth) + "<br>" + line.substring(columnWidth);
}
return line;
}
}

View File

@@ -1,58 +1,23 @@
<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN">
<!--
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Maven" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache Maven", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
/*
Copyright 2009 Dmitry Naumenko (dm.naumenko@gmail.com)
This file is part of Java Diff Utills Library.
Java Diff Utills Library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Java Diff Utills Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Java Diff Utills Library. If not, see <http://www.gnu.org/licenses/>.
*/
-->
<html>
<head>
@@ -61,8 +26,8 @@
<title></title>
</head>
<body>
<p>
The {@link org.apache.maven.jrcs.diff.myers diff.myers} package
<p>
The {@link difflib.myers diff.myers} package
implements <a href=
"http://www.cs.arizona.edu/people/gene/">Gene Myers</a>'
differencing algorithm.
@@ -71,10 +36,7 @@
Myer's algorithm produces optimum results (minimum diffs), but
consumes considerably more memory than SimpleDiff, so its not
suitable for very large files.
</p>
</p>
@author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a>
@version $Id: package.html 60 2003-05-10 18:56:10Z juanco $
@see Diff
@see org.apache.maven.jrcs.rcs.Archive
</body>
</html>

70
src/difflib/package.html Normal file
View File

@@ -0,0 +1,70 @@
<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN">
<!--
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Maven" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache Maven", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
-->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Cygwin (vers 1st February 2003), see www.w3.org">
<title></title>
</head>
<body>
<p>
The {@link difflib difflib} package
implements general operation with diff files.
</p>
@author <a href="mailto:dm.naumenko@gmail.com">Dmitry Naumenko</a>
</body>
</html>

View File

@@ -1,9 +1,11 @@
package testcase.diffutills;
import java.util.*;
import java.util.Arrays;
import java.util.List;
import junit.framework.TestCase;
import difflib.*;
import difflib.DiffUtils;
import difflib.Patch;
public class PatchTest extends TestCase {
private List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
@@ -17,16 +19,28 @@ public class PatchTest extends TestCase {
public void testPatch_Insert() {
Patch patch = DiffUtils.diff(insertTest_from, insertTest_to);
assertEquals(insertTest_to, DiffUtils.patch(insertTest_from, patch));
try {
assertEquals(insertTest_to, DiffUtils.patch(insertTest_from, patch));
} catch (Exception e) {
e.printStackTrace();
}
}
public void testPatch_Delete() {
Patch patch = DiffUtils.diff(deleteTest_from, deleteTest_to);
assertEquals(deleteTest_to, DiffUtils.patch(deleteTest_from, patch));
try {
assertEquals(deleteTest_to, DiffUtils.patch(deleteTest_from, patch));
} catch (Exception e) {
e.printStackTrace();
}
}
public void testPatch_Change() {
Patch patch = DiffUtils.diff(changeTest_from, changeTest_to);
assertEquals(changeTest_to, DiffUtils.patch(changeTest_from, patch));
try {
assertEquals(changeTest_to, DiffUtils.patch(changeTest_from, patch));
} catch (Exception e) {
e.printStackTrace();
}
}
}