package floobits.common.dmp;
import java.util.LinkedList;
public class FlooDmp extends diff_match_patch {
public Object[] patch_apply(LinkedList<Patch> patches, String text) {
if (patches.isEmpty()) {
return new Object[]{text, new boolean[0]};
}
// Deep copy the patches so that no changes are made to originals.
patches = patch_deepCopy(patches);
String nullPadding = patch_addPadding(patches);
final int np_len = nullPadding.length();
text = nullPadding + text + nullPadding;
patch_splitMax(patches);
int x = 0;
// delta keeps track of the offset between the expected and actual location
// of the previous patch. If there are patches expected at positions 10 and
// 20, but the first patch was found at 12, delta is 2 and the second patch
// has an effective expected position of 22.
int delta = 0;
boolean[] results = new boolean[patches.size()];
Object[] positions = new FlooPatchPosition[patches.size()];
for (Patch aPatch : patches) {
FlooPatchPosition position = new FlooPatchPosition(3, 0, "");
int expected_loc = aPatch.start2 + delta;
String text1 = diff_text1(aPatch.diffs);
int start_loc;
int end_loc = -1;
if (text1.length() > this.Match_MaxBits) {
// patch_splitMax will only provide an oversized pattern in the case of
// a monster delete.
start_loc = match_main(text,
text1.substring(0, this.Match_MaxBits), expected_loc);
if (start_loc != -1) {
end_loc = match_main(text,
text1.substring(text1.length() - this.Match_MaxBits),
expected_loc + text1.length() - this.Match_MaxBits);
if (end_loc == -1 || start_loc >= end_loc) {
// Can't find valid trailing context. Drop this patch.
start_loc = -1;
}
}
} else {
start_loc = match_main(text, text1, expected_loc);
}
if (start_loc == -1) {
// No match found. :(
results[x] = false;
// Subtract the delta for this failed patch from subsequent patches.
delta -= aPatch.length2 - aPatch.length1;
} else {
// Found a match. :)
results[x] = true;
delta = start_loc - expected_loc;
String text2;
if (end_loc == -1) {
text2 = text.substring(start_loc,
Math.min(start_loc + text1.length(), text.length()));
} else {
text2 = text.substring(start_loc,
Math.min(end_loc + this.Match_MaxBits, text.length()));
}
if (text1.equals(text2)) {
// Perfect match, just shove the replacement text in.
String replacement_str = diff_text2(aPatch.diffs);
text = text.substring(0, start_loc) + replacement_str
+ text.substring(start_loc + text1.length());
position = new FlooPatchPosition(start_loc, text1.length(), replacement_str);
} else {
// Imperfect match. Run a diff to get a framework of equivalent
// indices.
LinkedList<Diff> diffs = diff_main(text1, text2, false);
if (text1.length() > this.Match_MaxBits
&& diff_levenshtein(diffs) / (float) text1.length()
> this.Patch_DeleteThreshold) {
// The end points match, but the content is unacceptably bad.
results[x] = false;
} else {
diff_cleanupSemanticLossless(diffs);
int index1 = 0;
int delete_len = 0;
String inserted_text = "";
for (Diff aDiff : aPatch.diffs) {
if (aDiff.operation != Operation.EQUAL) {
int index2 = diff_xIndex(diffs, index1);
if (aDiff.operation == Operation.INSERT) {
// Insertion
text = text.substring(0, start_loc + index2) + aDiff.text
+ text.substring(start_loc + index2);
inserted_text += aDiff.text;
} else if (aDiff.operation == Operation.DELETE) {
// Deletion
int diff_index = diff_xIndex(diffs, index1 + aDiff.text.length());
text = text.substring(0, start_loc + index2)
+ text.substring(start_loc + diff_index);
delete_len += (diff_index - index2);
}
}
if (aDiff.operation != Operation.DELETE) {
index1 += aDiff.text.length();
}
}
position = new FlooPatchPosition(start_loc, delete_len, inserted_text);
}
}
}
final int text_len = text.length();
if (position.start < np_len) {
position.end -= np_len - position.start;
position.text = position.text.substring(Math.min(np_len - position.start, position.text.length()));
position.start = 0;
} else {
position.start -= np_len;
}
final int too_close = (position.start + position.text.length()) - (text_len - 2 * np_len);
if (too_close > 0){
int start = position.text.length() - too_close;
start = start < 0 ? 0 : start;
position.text = position.text.substring(0, start);
}
positions[x] = position;
x++;
}
// Strip the padding off.
text = text.substring(nullPadding.length(), text.length()
- nullPadding.length());
return new Object[]{text, results, positions};
}
}