+ * An edit script is the most general view of the differences between two + * sequences. It is built as the result of the comparison between two sequences + * by the {@link SequencesComparator SequencesComparator} class. The user can + * walk through it using the visitor design pattern. + *
+ *+ * It is guaranteed that the objects embedded in the {@link InsertCommand insert + * commands} come from the second sequence and that the objects embedded in + * either the {@link DeleteCommand delete commands} or {@link KeepCommand keep + * commands} come from the first sequence. This can be important if subclassing + * is used for some elements in the first sequence and the {@code equals} + * method is specialized. + *
+ *
+ * ATTRIBUTION NOTICE:
+ * This class contains source code copied from
+ * Apache commons-collection4
+ *
+ *
+ * ATTRIBUTION NOTICE:
+ * This class contains source code copied from
+ * Apache commons-collection4
+ *
+ *
+ * It is the functional sibling of {@link java.util.Comparator}; {@link Equator} is to + * {@link Object} as {@link java.util.Comparator} is to {@link java.lang.Comparable}. + *
+ * + * @param
+ * Copied from Apache commons-collections
+ *
+ * @param
+ * When two objects sequences are compared through the
+ * {@link SequencesComparator#getScript SequencesComparator.getScript} method,
+ * the result is provided has a {@link EditScript script} containing the commands
+ * that progressively transform the first sequence into the second one.
+ *
+ * There are only three types of commands, all of which are subclasses of this
+ * abstract class. Each command is associated with one object belonging to at
+ * least one of the sequences. These commands are {@link InsertCommand
+ * InsertCommand} which correspond to an object of the second sequence being
+ * inserted into the first sequence, {@link DeleteCommand DeleteCommand} which
+ * correspond to an object of the first sequence being removed and
+ * {@link KeepCommand KeepCommand} which correspond to an object of the first
+ * sequence which {@code equals} an object in the second sequence. It is
+ * guaranteed that comparison is always performed this way (i.e. the
+ * {@code equals} method of the object from the first sequence is used and
+ * the object passed as an argument comes from the second sequence) ; this can
+ * be important if subclassing is used for some elements in the first sequence
+ * and the {@code equals} method is specialized.
+ *
+ * This method is invoked for each commands belonging to
+ * an {@link EditScript EditScript}, in order to implement the visitor design pattern
+ *
+ * @param visitor the visitor to be accepted
+ */
+ public abstract void accept(CommandVisitor
+ * When one object of the first sequence {@code equals} another objects in
+ * the second sequence at the right place, the {@link EditScript edit script}
+ * transforming the first sequence into the second sequence uses an instance of
+ * this class to represent the keeping of this object. The objects embedded in
+ * these type of commands always come from the first sequence.
+ *
+ * When one object of the second sequence has no corresponding object in the
+ * first sequence at the right place, the {@link EditScript edit script}
+ * transforming the first sequence into the second sequence uses an instance of
+ * this class to represent the insertion of this object. The objects embedded in
+ * these type of commands always come from the second sequence.
+ *
+ * When one object of the first sequence has no corresponding object in the
+ * second sequence at the right place, the {@link EditScript edit script}
+ * transforming the first sequence into the second sequence uses an instance of
+ * this class to represent the deletion of this object. The objects embedded in
+ * these type of commands always come from the first sequence.
+ *
+ * Users should implement this interface in order to walk through
+ * the {@link EditScript EditScript} object created by the comparison
+ * of two sequences. This is a direct application of the visitor
+ * design pattern. The {@link EditScript#visit EditScript.visit}
+ * method takes an object implementing this interface as an argument,
+ * it will perform the loop over all commands in the script and the
+ * proper methods of the user class will be called as the commands are
+ * encountered.
+ *
+ * The implementation of the user visitor class will depend on the
+ * need. Here are two examples.
+ *
+ * The first example is a visitor that build the longest common
+ * subsequence:
+ *
+ * The second example is a visitor that shows the commands and the way
+ * they transform the first sequence into the second one:
+ *
+ * The two sequences can hold any object type, as only the {@code equals}
+ * method is used to compare the elements of the sequences. It is guaranteed
+ * that the comparisons will always be done as {@code o1.equals(o2)} where
+ * {@code o1} belongs to the first sequence and {@code o2} belongs to
+ * the second sequence. This can be important if subclassing is used for some
+ * elements in the first sequence and the {@code equals} method is
+ * specialized.
+ *
+ * Comparison can be seen from two points of view: either as giving the smallest
+ * modification allowing to transform the first sequence into the second one, or
+ * as giving the longest sequence which is a subsequence of both initial
+ * sequences. The {@code equals} method is used to compare objects, so any
+ * object can be put into sequences. Modifications include deleting, inserting
+ * or keeping one object, starting from the beginning of the first sequence.
+ *
+ * This class implements the comparison algorithm, which is the very efficient
+ * algorithm from Eugene W. Myers
+ *
+ * An O(ND) Difference Algorithm and Its Variations. This algorithm produces
+ * the shortest possible
+ * {@link EditScript edit script}
+ * containing all the
+ * {@link EditCommand commands}
+ * needed to transform the first sequence into the second one.
+ *
+ * ATTRIBUTION NOTICE:
+ * Creates a new instance of SequencesComparator using a {@link DefaultEquator}.
+ *
+ * It is guaranteed that the comparisons will always be done as
+ * {@code o1.equals(o2)} where {@code o1} belongs to the first
+ * sequence and {@code o2} belongs to the second sequence. This can be
+ * important if subclassing is used for some elements in the first sequence
+ * and the {@code equals} method is specialized.
+ *
+ * @param sequence1 first sequence to be compared
+ * @param sequence2 second sequence to be compared
+ */
+ public SequencesComparator(final List
+ * Creates a new instance of SequencesComparator with a custom {@link Equator}.
+ *
+ * It is guaranteed that the comparisons will always be done as
+ * {@code Equator.equate(o1, o2)} where {@code o1} belongs to the first
+ * sequence and {@code o2} belongs to the second sequence.
+ *
+ * @param sequence1 first sequence to be compared
+ * @param sequence2 second sequence to be compared
+ * @param equator the equator to use for testing object equality
+ */
+ public SequencesComparator(final List
+ * It is guaranteed that the objects embedded in the {@link InsertCommand
+ * insert commands} come from the second sequence and that the objects
+ * embedded in either the {@link DeleteCommand delete commands} or
+ * {@link KeepCommand keep commands} come from the first sequence. This can
+ * be important if subclassing is used for some elements in the first
+ * sequence and the {@code equals} method is specialized.
+ *
+ * @return the edit script resulting from the comparison of the two
+ * sequences
+ */
+ public EditScript
+ * The snake is found using the MYERS Algorithm (this algorithms has
+ * also been implemented in the GNU diff program). This algorithm is
+ * explained in Eugene Myers article:
+ *
+ * An O(ND) Difference Algorithm and Its Variations.
+ *
+ * @param start1 the begin of the first sequence to be compared
+ * @param end1 the end of the first sequence to be compared
+ * @param start2 the begin of the second sequence to be compared
+ * @param end2 the end of the second sequence to be compared
+ * @return the middle snake
+ */
+ private Snake getMiddleSnake(final int start1, final int end1, final int start2, final int end2) {
+ // Myers Algorithm
+ // Initialisations
+ final int m = end1 - start1;
+ final int n = end2 - start2;
+ if (m == 0 || n == 0) {
+ return null;
+ }
+
+ final int delta = m - n;
+ final int sum = n + m;
+ final int offset = (sum % 2 == 0 ? sum : sum + 1) / 2;
+ vDown[1+offset] = start1;
+ vUp[1+offset] = end1 + 1;
+
+ for (int d = 0; d <= offset; ++d) {
+ // Down
+ for (int k = -d; k <= d; k += 2) {
+ // First step
+
+ final int i = k + offset;
+ if (k == -d || k != d && vDown[i-1] < vDown[i+1]) {
+ vDown[i] = vDown[i+1];
+ } else {
+ vDown[i] = vDown[i-1] + 1;
+ }
+
+ int x = vDown[i];
+ int y = x - start1 + start2 - k;
+
+ while (x < end1 && y < end2 && equator.equate(sequence1.get(x), sequence2.get(y))) {
+ vDown[i] = ++x;
+ ++y;
+ }
+ // Second step
+ if (delta % 2 != 0 && delta - d <= k && k <= delta + d) {
+ if (vUp[i-delta] <= vDown[i]) { // NOPMD
+ return buildSnake(vUp[i-delta], k + start1 - start2, end1, end2);
+ }
+ }
+ }
+
+ // Up
+ for (int k = delta - d; k <= delta + d; k += 2) {
+ // First step
+ final int i = k + offset - delta;
+ if (k == delta - d
+ || k != delta + d && vUp[i+1] <= vUp[i-1]) {
+ vUp[i] = vUp[i+1] - 1;
+ } else {
+ vUp[i] = vUp[i-1];
+ }
+
+ int x = vUp[i] - 1;
+ int y = x - start1 + start2 - k;
+ while (x >= start1 && y >= start2
+ && equator.equate(sequence1.get(x), sequence2.get(y))) {
+ vUp[i] = x--;
+ y--;
+ }
+ // Second step
+ if (delta % 2 == 0 && -d <= k && k <= d ) {
+ if (vUp[i] <= vDown[i + delta]) { // NOPMD
+ return buildSnake(vUp[i], k + start1 - start2, end1, end2);
+ }
+ }
+ }
+ }
+
+ // this should not happen
+ throw new RuntimeException("Internal Error");
+ }
+
+
+ /**
+ * Build an edit script.
+ *
+ * @param start1 the begin of the first sequence to be compared
+ * @param end1 the end of the first sequence to be compared
+ * @param start2 the begin of the second sequence to be compared
+ * @param end2 the end of the second sequence to be compared
+ * @param script the edited script
+ */
+ private void buildScript(final int start1, final int end1, final int start2, final int end2,
+ final EditScript
+ * ATTRIBUTION NOTICE:
+ * import org.apache.commons.collections4.comparators.sequence.CommandVisitor;
+ *
+ * import java.util.ArrayList;
+ *
+ * public class LongestCommonSubSequence implements CommandVisitor {
+ *
+ * public LongestCommonSubSequence() {
+ * a = new ArrayList();
+ * }
+ *
+ * public void visitInsertCommand(Object object) {
+ * }
+ *
+ * public void visitKeepCommand(Object object) {
+ * a.add(object);
+ * }
+ *
+ * public void visitDeleteCommand(Object object) {
+ * }
+ *
+ * public Object[] getSubSequence() {
+ * return a.toArray();
+ * }
+ *
+ * private ArrayList a;
+ *
+ * }
+ *
+ *
+ * import org.apache.commons.collections4.comparators.sequence.CommandVisitor;
+ *
+ * import java.util.Arrays;
+ * import java.util.ArrayList;
+ * import java.util.Iterator;
+ *
+ * public class ShowVisitor implements CommandVisitor {
+ *
+ * public ShowVisitor(Object[] sequence1) {
+ * v = new ArrayList();
+ * v.addAll(Arrays.asList(sequence1));
+ * index = 0;
+ * }
+ *
+ * public void visitInsertCommand(Object object) {
+ * v.insertElementAt(object, index++);
+ * display("insert", object);
+ * }
+ *
+ * public void visitKeepCommand(Object object) {
+ * ++index;
+ * display("keep ", object);
+ * }
+ *
+ * public void visitDeleteCommand(Object object) {
+ * v.remove(index);
+ * display("delete", object);
+ * }
+ *
+ * private void display(String commandName, Object object) {
+ * System.out.println(commandName + " " + object + " ->" + this);
+ * }
+ *
+ * public String toString() {
+ * StringBuffer buffer = new StringBuffer();
+ * for (Iterator iter = v.iterator(); iter.hasNext();) {
+ * buffer.append(' ').append(iter.next());
+ * }
+ * return buffer.toString();
+ * }
+ *
+ * private ArrayList v;
+ * private int index;
+ *
+ * }
+ *
+ *
+ * @since 4.0
+ */
+ public static interface CommandVisitor
+ * This class contains source code copied from
+ * Apache commons-collection4
+ *
+ *
+ * This class contains source code copied from
+ * Apache commons-collection4
+ *
+ *