package fi.otavanopisto.muikku.plugins.material.coops;
import java.util.LinkedList;
import com.sksamuel.diffpatch.DiffMatchPatch;
import com.sksamuel.diffpatch.DiffMatchPatch.Diff;
import com.sksamuel.diffpatch.DiffMatchPatch.Operation;
import com.sksamuel.diffpatch.DiffMatchPatch.Patch;
import fi.foyt.coops.CoOpsConflictException;
public class CoOpsDmpDiffAlgorithm implements CoOpsDiffAlgorithm {
@Override
public String getName() {
return "dmp";
}
@Override
public String patch(String data, String patch) throws CoOpsConflictException {
DiffMatchPatch diffMatchPatch = new DiffMatchPatch();
LinkedList<Patch> patches = new LinkedList<Patch>(diffMatchPatch.patch_fromText(patch));
Object[] patchResult = diffMatchPatch.patch_apply(patches, data);
for (boolean applied : (boolean[]) patchResult[1]) {
if (!applied) {
throw new CoOpsConflictException();
}
}
return (String) patchResult[0];
}
@Override
public String unpatch(String data, String patch) throws CoOpsConflictException {
DiffMatchPatch diffMatchPatch = new DiffMatchPatch();
LinkedList<Patch> patches = createUnpatch(new LinkedList<Patch>(diffMatchPatch.patch_fromText(patch)));
Object[] patchResult = diffMatchPatch.patch_apply(patches, data);
for (boolean applied : (boolean[]) patchResult[1]) {
if (!applied) {
throw new CoOpsConflictException();
}
}
return (String) patchResult[0];
}
private LinkedList<Patch> createUnpatch(LinkedList<Patch> patches) {
LinkedList<Patch> result = new LinkedList<>();
// Switch places of DIFF_DELETE and DIFF_INSERT
for (int patchIndex = 0, patchesLength = patches.size(); patchIndex < patchesLength; patchIndex++) {
Patch patch = patches.get(patchIndex);
Patch unpatch = new Patch();
unpatch.length1 = patch.length1;
unpatch.length2 = patch.length2;
unpatch.start1 = patch.start1;
unpatch.start2 = patch.start2;
for (int diffIndex = 0, diffsLength = patch.diffs.size(); diffIndex < diffsLength; diffIndex++) {
Diff diff = patch.diffs.get(diffIndex);
switch (diff.operation) {
case DELETE:
patch.diffs.add(new Diff(Operation.INSERT, diff.text));
break;
case INSERT:
patch.diffs.add(new Diff(Operation.DELETE, diff.text));
break;
case EQUAL:
patch.diffs.add(new Diff(diff.operation, diff.text));
break;
}
}
result.add(unpatch);
}
return result;
}
}