001: /*
002: * Copyright 2007 Outerthought bvba and Schaubroeck nv
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.outerj.daisy.diff.html;
017:
018: import java.util.LinkedList;
019: import java.util.List;
020: import java.util.Locale;
021:
022: import org.eclipse.compare.internal.LCSSettings;
023: import org.eclipse.compare.rangedifferencer.RangeDifference;
024: import org.eclipse.compare.rangedifferencer.RangeDifferencer;
025: import org.xml.sax.SAXException;
026:
027: /**
028: * Takes two {@link TextNodeComparator} instances, computes the difference
029: * between them, marks the changes, and outputs a merged tree to a
030: * {@link HtmlSaxDiffOutput} instance.
031: */
032: public class HTMLDiffer {
033:
034: private HtmlSaxDiffOutput output;
035:
036: public HTMLDiffer(HtmlSaxDiffOutput dm) {
037: output = dm;
038: }
039:
040: public void diff(TextNodeComparator leftComparator,
041: TextNodeComparator rightComparator) throws SAXException {
042: LCSSettings settings = new LCSSettings();
043: settings.setUseGreedyMethod(false);
044: // settings.setPowLimit(1.5);
045: // settings.setTooLong(100000*100000);
046:
047: RangeDifference[] differences = RangeDifferencer
048: .findDifferences(settings, leftComparator,
049: rightComparator);
050:
051: List<RangeDifference> pdifferences = preProcess(differences,
052: leftComparator);
053:
054: int currentIndexLeft = 0;
055: int currentIndexRight = 0;
056: for (RangeDifference d : pdifferences) {
057:
058: if (d.leftStart() > currentIndexLeft) {
059: rightComparator.handlePossibleChangedPart(
060: currentIndexLeft, d.leftStart(),
061: currentIndexRight, d.rightStart(),
062: leftComparator);
063: }
064: if (d.leftLength() > 0) {
065: rightComparator.markAsDeleted(d.leftStart(), d
066: .leftEnd(), leftComparator, d.rightStart());
067: }
068: rightComparator.markAsNew(d.rightStart(), d.rightEnd());
069:
070: currentIndexLeft = d.leftEnd();
071: currentIndexRight = d.rightEnd();
072: }
073: if (currentIndexLeft < leftComparator.getRangeCount()) {
074: rightComparator.handlePossibleChangedPart(currentIndexLeft,
075: leftComparator.getRangeCount(), currentIndexRight,
076: rightComparator.getRangeCount(), leftComparator);
077: }
078:
079: rightComparator.expandWhiteSpace();
080: output.toHTML(rightComparator.getBodyNode());
081: }
082:
083: private List<RangeDifference> preProcess(
084: RangeDifference[] differences,
085: TextNodeComparator leftComparator) {
086:
087: List<RangeDifference> newRanges = new LinkedList<RangeDifference>();
088:
089: for (int i = 0; i < differences.length; i++) {
090:
091: int leftStart = differences[i].leftStart();
092: int leftEnd = differences[i].leftEnd();
093: int rightStart = differences[i].rightStart();
094: int rightEnd = differences[i].rightEnd();
095: int kind = differences[i].kind();
096:
097: int leftLength = leftEnd - leftStart;
098: int rightLength = rightEnd - rightStart;
099:
100: while (i + 1 < differences.length
101: && differences[i + 1].kind() == kind
102: && score(leftLength, differences[i + 1]
103: .leftLength(), rightLength,
104: differences[i + 1].rightLength()) > (differences[i + 1]
105: .leftStart() - leftEnd)) {
106: leftEnd = differences[i + 1].leftEnd();
107: rightEnd = differences[i + 1].rightEnd();
108: leftLength = leftEnd - leftStart;
109: rightLength = rightEnd - rightStart;
110: i++;
111: }
112:
113: newRanges.add(new RangeDifference(kind, rightStart,
114: rightEnd - rightStart, leftStart, leftEnd
115: - leftStart));
116: }
117:
118: return newRanges;
119: }
120:
121: public static double score(int... numbers) {
122: if ((numbers[0] == 0 && numbers[1] == 0)
123: || (numbers[2] == 0 && numbers[3] == 0))
124: return 0;
125:
126: double d = 0;
127: for (double number : numbers) {
128: while (number > 3) {
129: d += 3;
130: number -= 3;
131: number *= 0.5;
132: }
133: d += number;
134:
135: }
136: return d / (1.5 * numbers.length);
137: }
138: }
|