DocumentDiff3.java 7.44 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.day.util.diff;

import com.day.util.diff.*;

import java.io.IOException;
import java.io.StringWriter;

public class DocumentDiff3 {
    static final String CVS_ID = "$URL$ $Rev$ $Date$";
    private final Document base;
    private final Document left;
    private final Document right;
    private final Diff.Change leftChanges;
    private final Diff.Change rightChanges;
    private final Hunk3 hunks = new Hunk3(null, null, null, null);
    private boolean hasConflicts;

    public DocumentDiff3(Document base, Document left, Document right) {
        this.base = base;
        this.left = left;
        this.right = right;
        Object[] baseElems = base.getElements();
        Object[] leftElems = left.getElements();
        Object[] rightElems = right.getElements();
        this.leftChanges = new Diff(baseElems, leftElems).diff_2(false);
        this.rightChanges = new Diff(baseElems, rightElems).diff_2(false);
        this.initHunks();
    }

    public Hunk3 getHunks() {
        return this.hunks.next();
    }

    public boolean hasConflicts() {
        return this.hasConflicts;
    }

    public void write(StringBuffer buf, String lineSeparator, boolean showBase) {
        try {
            StringWriter w = new StringWriter();
            this.write(new DiffWriter(w, lineSeparator), showBase);
            buf.append(w.getBuffer());
        }
        catch (IOException e) {
            throw new IllegalStateException(e.toString());
        }
    }

    public void write(DiffWriter w, boolean showBase) throws IOException {
        for (Hunk3 hunk = this.hunks.next(); hunk != null; hunk = hunk.next()) {
            hunk.write(w, showBase);
        }
        w.flush();
    }

    private void initHunks() {
        MyChange[] changes = new MyChange[]{this.wrap(this.leftChanges), this.wrap(this.rightChanges)};
        int basePos = 0;
        Hunk3 hunk = this.hunks;
        while (changes[0] != null || changes[1] != null) {
            MyChange[] using = new MyChange[]{null, null};
            MyChange[] lastUsing = new MyChange[]{null, null};
            int baseIdx = changes[0] == null ? 1 : (changes[1] == null ? 0 : (changes[0].low0 < changes[1].low0 ? 0 : 1));
            int highIdx = baseIdx;
            int highMark = changes[highIdx].high0;
            using[highIdx] = lastUsing[highIdx] = changes[highIdx];
            changes[highIdx] = changes[highIdx].next;
            lastUsing[highIdx].next = null;
            int otherIdx = highIdx ^ 1;
            MyChange other = changes[otherIdx];
            while (other != null && other.low0 <= highMark) {
                if (using[otherIdx] == null) {
                    using[otherIdx] = other;
                } else {
                    using[otherIdx].next = other;
                }
                lastUsing[otherIdx] = other;
                changes[otherIdx] = changes[otherIdx].next;
                other.next = null;
                if (other.high0 > highMark) {
                    highIdx ^= 1;
                    highMark = other.high0;
                }
                otherIdx = highIdx ^ 1;
                other = changes[otherIdx];
            }
            int lowMark = using[baseIdx].low0;
            if (basePos < lowMark) {
                hunk = new Hunk3(new Range(this.base, basePos, lowMark), null, null, hunk);
                basePos = lowMark;
            }
            int[] deltaLow = new int[]{0, 0};
            if (using[baseIdx ^ 1] != null) {
                deltaLow[baseIdx ^ 1] = using[baseIdx ^ 1].low0 - using[baseIdx].low0;
            }
            int[] deltaHigh = new int[]{0, 0};
            if (using[highIdx ^ 1] != null) {
                deltaHigh[highIdx ^ 1] = using[highIdx].high0 - using[highIdx ^ 1].high0;
            }
            Range leftRange = null;
            Range rightRange = null;
            if (using[0] != null) {
                leftRange = new Range(this.left, using[0].low1 - deltaLow[0], lastUsing[0].high1 + deltaHigh[0]);
            }
            if (using[1] != null) {
                rightRange = new Range(this.right, using[1].low1 - deltaLow[1], lastUsing[1].high1 + deltaHigh[1]);
            }
            boolean conflict = false;
            if (leftRange != null && rightRange != null) {
                if (leftRange.len() == rightRange.len()) {
                    for (int i = 0; i < leftRange.len(); ++i) {
                        if (this.left.getElements()[leftRange.low + i].equals(this.right.getElements()[rightRange.low + i])) continue;
                        conflict = true;
                        break;
                    }
                    if (!conflict) {
                        rightRange = null;
                    }
                } else {
                    conflict = true;
                }
            }
            int baseHigh = using[highIdx].high0;
            Range baseRange = new Range(this.base, basePos, baseHigh);
            basePos = baseHigh;
            hunk = new Hunk3(baseRange, leftRange, rightRange, hunk);
            this.hasConflicts |= conflict;
        }
        if (basePos < this.base.getElements().length) {
            new Hunk3(new Range(this.base, basePos, this.base.getElements().length), null, null, hunk);
        }
    }

    private MyChange wrap(Diff.Change df) {
        MyChange first = null;
        MyChange c = null;
        while (df != null) {
            c = new MyChange(df.line0, df.line1, df.deleted, df.inserted, c);
            if (first == null) {
                first = c;
            }
            df = df.nextChange;
        }
        return first;
    }

    private void dump(MyChange c, Document left, Document right) {
        while (c != null) {
            int i;
            if (c.isInsert()) {
                for (i = 0; i < c.high1 - c.low1; ++i) {
                    this.dump(0, c.low0 + i, c.low1 + i, "+", c.low1 + i, right);
                }
            } else if (c.isDelete()) {
                for (i = 0; i < c.high0 - c.low0; ++i) {
                    this.dump(0, c.low0 + i, c.low1 + i, "-", c.low0 + i, left);
                }
            } else {
                for (i = 0; i < c.high1 - c.low1; ++i) {
                    this.dump(0, c.low0 + i, c.low1 + i, "~", c.low1 + i, right);
                }
            }
            c = c.next;
        }
    }

    private void dump(int b, int l, int r, String prefix, int i, Document doc) {
        StringBuffer buf = new StringBuffer();
        buf.append("(").append(b);
        buf.append(", ").append(l);
        buf.append(", ").append(r);
        buf.append(") ").append(prefix);
        buf.append(doc.getElements()[i]);
        System.out.println(buf);
    }

    private static class MyChange {
        private final int low0;
        private final int low1;
        private final int high0;
        private final int high1;
        private MyChange next;

        public MyChange(int low0, int low1, int len0, int len1, MyChange prev) {
            this.low0 = low0;
            this.low1 = low1;
            this.high0 = low0 + len0;
            this.high1 = low1 + len1;
            if (prev != null) {
                prev.next = this;
            }
        }

        public boolean isDelete() {
            return this.low1 == this.high1;
        }

        public boolean isInsert() {
            return this.low0 == this.high0;
        }

        public String toString() {
            return "(" + this.low0 + "-" + this.high0 + "),(" + this.low1 + "-" + this.high1 + ")";
        }
    }

}