127 lines
4.2 KiB
Java
127 lines
4.2 KiB
Java
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You 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.apache.commons.text.diff;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* This class handles sequences of replacements resulting from a comparison.
|
|
* <p>
|
|
* The comparison of two objects sequences leads to the identification of common
|
|
* parts and parts which only belong to the first or to the second sequence. The
|
|
* common parts appear in the edit script in the form of <em>keep</em> commands,
|
|
* they can be considered as synchronization objects between the two sequences.
|
|
* These synchronization objects split the two sequences in synchronized
|
|
* sub-sequences. The first sequence can be transformed into the second one by
|
|
* replacing each synchronized sub-sequence of the first sequence by the
|
|
* corresponding sub-sequence of the second sequence. This is a synthetic way to
|
|
* see an {@link EditScript edit script}, replacing individual
|
|
* {@link DeleteCommand delete}, {@link KeepCommand keep} and
|
|
* {@link InsertCommand insert} commands by fewer replacements acting on
|
|
* complete sub-sequences.
|
|
* </p>
|
|
* <p>
|
|
* This class is devoted to perform this interpretation. It visits an
|
|
* {@link EditScript edit script} (because it implements the
|
|
* {@link CommandVisitor CommandVisitor} interface) and calls a user-supplied
|
|
* handler implementing the {@link ReplacementsHandler ReplacementsHandler}
|
|
* interface to process the sub-sequences.
|
|
* </p>
|
|
*
|
|
* @see ReplacementsHandler
|
|
* @see EditScript
|
|
* @see StringsComparator
|
|
*
|
|
* @param <T> object type
|
|
* @since 1.0
|
|
*/
|
|
public class ReplacementsFinder<T> implements CommandVisitor<T> {
|
|
|
|
/**
|
|
* List of pending insertions.
|
|
*/
|
|
private final List<T> pendingInsertions;
|
|
|
|
/**
|
|
* List of pending deletions.
|
|
*/
|
|
private final List<T> pendingDeletions;
|
|
|
|
/**
|
|
* Count of elements skipped.
|
|
*/
|
|
private int skipped;
|
|
|
|
/** Handler to call when synchronized sequences are found. */
|
|
private final ReplacementsHandler<T> handler;
|
|
|
|
/**
|
|
* Constructs a new instance of {@link ReplacementsFinder}.
|
|
*
|
|
* @param handler handler to call when synchronized sequences are found
|
|
*/
|
|
public ReplacementsFinder(final ReplacementsHandler<T> handler) {
|
|
pendingInsertions = new ArrayList<>();
|
|
pendingDeletions = new ArrayList<>();
|
|
skipped = 0;
|
|
this.handler = handler;
|
|
}
|
|
|
|
/**
|
|
* Add an object to the pending deletions set.
|
|
*
|
|
* @param object object to delete
|
|
*/
|
|
@Override
|
|
public void visitDeleteCommand(final T object) {
|
|
pendingDeletions.add(object);
|
|
}
|
|
|
|
/**
|
|
* Add an object to the pending insertions set.
|
|
*
|
|
* @param object object to insert
|
|
*/
|
|
@Override
|
|
public void visitInsertCommand(final T object) {
|
|
pendingInsertions.add(object);
|
|
}
|
|
|
|
/**
|
|
* Handle a synchronization object.
|
|
* <p>
|
|
* When a synchronization object is identified, the pending insertions and
|
|
* pending deletions sets are provided to the user handler as subsequences.
|
|
* </p>
|
|
*
|
|
* @param object synchronization object detected
|
|
*/
|
|
@Override
|
|
public void visitKeepCommand(final T object) {
|
|
if (pendingDeletions.isEmpty() && pendingInsertions.isEmpty()) {
|
|
++skipped;
|
|
} else {
|
|
handler.handleReplacement(skipped, pendingDeletions, pendingInsertions);
|
|
pendingDeletions.clear();
|
|
pendingInsertions.clear();
|
|
skipped = 1;
|
|
}
|
|
}
|
|
|
|
}
|