package org.webcat.diff; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; //------------------------------------------------------------------------- /** * A linked list of {@link Diff} objects that provides additional methods for * operating on the list or reconstituting the original lists. * * @param <T> the type of the item in the list * * @author Tony Allevato * @author Last changed by $Author: stedwar2 $ * @version $Revision: 1.2 $, $Date: 2011/06/09 15:29:09 $ */ public class DiffList<T> extends LinkedList<Diff<T>> { //~ Methods ............................................................... // ---------------------------------------------------------- /** * Compute and return the source text (all equalities and deletions). * @return Source text. */ public List<T> computeFirstList() { ArrayList<T> list = new ArrayList<T>(); for (Diff<T> aDiff : this) { if (aDiff.operation != Diff.Operation.INSERT) { list.addAll(aDiff.list); } } return list; } // ---------------------------------------------------------- /** * Compute and return the destination text (all equalities and insertions). * @return Destination text. */ public List<T> computeSecondList() { ArrayList<T> list = new ArrayList<T>(); for (Diff<T> aDiff : this) { if (aDiff.operation != Diff.Operation.DELETE) { list.addAll(aDiff.list); } } return list; } // ---------------------------------------------------------- /** * Compute the Levenshtein distance; the number of inserted, deleted or * substituted characters. * @return Number of changes. */ public int getLevenshteinDistance() { int levenshtein = 0; int insertions = 0; int deletions = 0; for (Diff<T> aDiff : this) { switch (aDiff.operation) { case INSERT: insertions += aDiff.list.size(); break; case DELETE: deletions += aDiff.list.size(); break; case EQUAL: // A deletion and an insertion is one substitution. levenshtein += Math.max(insertions, deletions); insertions = 0; deletions = 0; break; } } levenshtein += Math.max(insertions, deletions); return levenshtein; } // ---------------------------------------------------------- /** * loc is a location in text1, compute and return the equivalent location * in text2. e.g. "The cat" vs "The big cat", 1->1, 5->8 * * @param loc * Location within text1. * @return Location within text2. */ public int translateIndex(int loc) { int chars1 = 0; int chars2 = 0; int last_chars1 = 0; int last_chars2 = 0; Diff<T> lastDiff = null; for (Diff<T> aDiff : this) { if (aDiff.operation != Diff.Operation.INSERT) { // Equality or deletion. chars1 += aDiff.list.size(); } if (aDiff.operation != Diff.Operation.DELETE) { // Equality or insertion. chars2 += aDiff.list.size(); } if (chars1 > loc) { // Overshot the location. lastDiff = aDiff; break; } last_chars1 = chars1; last_chars2 = chars2; } if (lastDiff != null && lastDiff.operation == Diff.Operation.DELETE) { // The location was deleted. return last_chars2; } // Add the remaining character length. return last_chars2 + (loc - last_chars1); } //~ Static/instance variables ............................................. private static final long serialVersionUID = 9136119555777279980L; }