All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.outerj.daisy.diff.tag.TagDiffer Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2007 Guy Van den Broeck
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.outerj.daisy.diff.tag;

import java.util.LinkedList;
import java.util.List;

import org.eclipse.compare.rangedifferencer.RangeDifference;
import org.eclipse.compare.rangedifferencer.RangeDifferencer;
import org.outerj.daisy.diff.output.TextDiffOutput;
import org.outerj.daisy.diff.output.TextDiffer;

/**
 * Takes 2 AtomSplitters and computes the difference between them. Output is
 * sent to a given HTMLSaxDiffOutput and tags are diffed
 * internally on a second iteration. The results are processed as to combine
 * small subsequent changes in to larger changes.
 */
public class TagDiffer implements TextDiffer{

    private TextDiffOutput output;

    public TagDiffer(TextDiffOutput output) {
        this.output = output;
    }

    /**
     * {@inheritDoc}
     */
    public void diff(IAtomSplitter leftComparator, IAtomSplitter rightComparator)
            throws Exception {

        RangeDifference[] differences = RangeDifferencer.findDifferences(
                leftComparator, rightComparator);

        List pdifferences = preProcess(differences,
                leftComparator);

        int rightAtom = 0;
        int leftAtom = 0;

        for (int i = 0; i < pdifferences.size(); i++) {

            parseNoChange(leftAtom, pdifferences.get(i).leftStart(), rightAtom,
                    pdifferences.get(i).rightStart(), leftComparator,
                    rightComparator);

            String leftString = leftComparator.substring(pdifferences.get(i)
                    .leftStart(), pdifferences.get(i).leftEnd());
            String rightString = rightComparator.substring(pdifferences.get(i)
                    .rightStart(), pdifferences.get(i).rightEnd());

            if (pdifferences.get(i).leftLength() > 0)
                output.addRemovedPart(leftString);

            if (pdifferences.get(i).rightLength() > 0)
                output.addAddedPart(rightString);

            rightAtom = pdifferences.get(i).rightEnd();
            leftAtom = pdifferences.get(i).leftEnd();

        }
        if (rightAtom < rightComparator.getRangeCount())
            parseNoChange(leftAtom, leftComparator.getRangeCount(), rightAtom,
                    rightComparator.getRangeCount(), leftComparator,
                    rightComparator);

    }

    private void parseNoChange(int beginLeft, int endLeft, int beginRight,
            int endRight, IAtomSplitter leftComparator,
            IAtomSplitter rightComparator) throws Exception {

        StringBuilder sb = new StringBuilder();

        /*
         * We can assume that the LCS is correct and that there are exacly as
         * many atoms left and right
         */
        while (beginLeft < endLeft) {

            while (beginLeft < endLeft
                    && !rightComparator.getAtom(beginRight)
                            .hasInternalIdentifiers()
                    && !leftComparator.getAtom(beginLeft)
                            .hasInternalIdentifiers()) {
                sb.append(rightComparator.getAtom(beginRight).getFullText());
                beginRight++;
                beginLeft++;
            }

            if (sb.length() > 0) {
                output.addClearPart(sb.toString());
                sb.setLength(0);
            }

            if (beginLeft < endLeft) {

                IAtomSplitter leftComparator2 = new ArgumentComparator(
                        leftComparator.getAtom(beginLeft).getFullText());
                IAtomSplitter rightComparator2 = new ArgumentComparator(
                        rightComparator.getAtom(beginRight).getFullText());

                RangeDifference[] differences2 = RangeDifferencer
                        .findDifferences(leftComparator2, rightComparator2);
                List pdifferences2 = preProcess(differences2,
                        2);

                int rightAtom2 = 0;
                for (int j = 0; j < pdifferences2.size(); j++) {
                    if (rightAtom2 < pdifferences2.get(j).rightStart()) {
                        output.addClearPart(rightComparator2.substring(
                                rightAtom2, pdifferences2.get(j).rightStart()));
                    }
                    if (pdifferences2.get(j).leftLength() > 0) {
                        output.addRemovedPart(leftComparator2.substring(
                                pdifferences2.get(j).leftStart(), pdifferences2
                                        .get(j).leftEnd()));
                    }
                    if (pdifferences2.get(j).rightLength() > 0) {
                        output.addAddedPart(rightComparator2.substring(
                                pdifferences2.get(j).rightStart(),
                                pdifferences2.get(j).rightEnd()));
                    }

                    rightAtom2 = pdifferences2.get(j).rightEnd();

                }
                if (rightAtom2 < rightComparator2.getRangeCount())
                    output.addClearPart(rightComparator2.substring(rightAtom2));
                beginLeft++;
                beginRight++;
            }

        }

    }

    private List preProcess(RangeDifference[] differences,
            IAtomSplitter leftComparator) {

        List newRanges = new LinkedList();

        for (int i = 0; i < differences.length; i++) {

            int leftStart = differences[i].leftStart();
            int leftEnd = differences[i].leftEnd();
            int rightStart = differences[i].rightStart();
            int rightEnd = differences[i].rightEnd();
            int kind = differences[i].kind();
            int temp = leftEnd;
            boolean connecting = true;

            while (connecting && i + 1 < differences.length
                    && differences[i + 1].kind() == kind) {

                int bridgelength = 0;

                int nbtokens = Math.max((leftEnd - leftStart),
                        (rightEnd - rightStart));
                if (nbtokens > 5) {
                    if (nbtokens > 10) {
                        bridgelength = 3;
                    } else
                        bridgelength = 2;
                }

				while (temp < differences[i + 1].leftStart()
						&& (leftComparator.getAtom(temp) instanceof DelimiterAtom || (bridgelength-- > 0))) {

					temp++;
				}
                if (temp == differences[i + 1].leftStart()) {
                    leftEnd = differences[i + 1].leftEnd();
                    rightEnd = differences[i + 1].rightEnd();
                    temp = leftEnd;
                    i++;
                } else {
                    connecting = false;
                    if (!(leftComparator.getAtom(temp) instanceof DelimiterAtom)) {
                        if (leftComparator.getAtom(temp).getFullText().equals(
                                " "))
                            throw new IllegalStateException(
                                    "space found aiaiai");
                    }
                }
            }
            newRanges.add(new RangeDifference(kind, rightStart, rightEnd
                    - rightStart, leftStart, leftEnd - leftStart));
        }

        return newRanges;
    }

    private List preProcess(RangeDifference[] differences,
            int span) {

        List newRanges = new LinkedList();

        for (int i = 0; i < differences.length; i++) {

            int leftStart = differences[i].leftStart();
            int leftEnd = differences[i].leftEnd();
            int rightStart = differences[i].rightStart();
            int rightEnd = differences[i].rightEnd();
            int kind = differences[i].kind();

            while (i + 1 < differences.length
                    && differences[i + 1].kind() == kind
                    && differences[i + 1].leftStart() <= leftEnd + span
                    && differences[i + 1].rightStart() <= rightEnd + span) {
                leftEnd = differences[i + 1].leftEnd();
                rightEnd = differences[i + 1].rightEnd();
                i++;
            }

            newRanges.add(new RangeDifference(kind, rightStart, rightEnd
                    - rightStart, leftStart, leftEnd - leftStart));
        }

        return newRanges;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy