ReplacementsFinder.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.collections4.sequence;

  18. import java.util.ArrayList;
  19. import java.util.List;

  20. /**
  21.  * This class handles sequences of replacements resulting from a comparison.
  22.  * <p>
  23.  * The comparison of two objects sequences leads to the identification of common
  24.  * parts and parts which only belong to the first or to the second sequence. The
  25.  * common parts appear in the edit script in the form of <em>keep</em> commands,
  26.  * they can be considered as synchronization objects between the two sequences.
  27.  * These synchronization objects split the two sequences in synchronized
  28.  * sub-sequences. The first sequence can be transformed into the second one by
  29.  * replacing each synchronized sub-sequence of the first sequence by the
  30.  * corresponding sub-sequence of the second sequence. This is a synthetic way to
  31.  * see an {@link EditScript edit script}, replacing individual
  32.  * {@link DeleteCommand delete}, {@link KeepCommand keep} and
  33.  * {@link InsertCommand insert} commands by fewer replacements acting on
  34.  * complete sub-sequences.
  35.  * </p>
  36.  * <p>
  37.  * This class is devoted to perform this interpretation. It visits an
  38.  * {@link EditScript edit script} (because it implements the
  39.  * {@link CommandVisitor CommandVisitor} interface) and calls a user-supplied
  40.  * handler implementing the {@link ReplacementsHandler ReplacementsHandler}
  41.  * interface to process the sub-sequences.
  42.  * </p>
  43.  *
  44.  * @param <T> the type of the input to the visit operations.
  45.  * @see ReplacementsHandler
  46.  * @see EditScript
  47.  * @see SequencesComparator
  48.  * @since 4.0
  49.  */
  50. public class ReplacementsFinder<T> implements CommandVisitor<T> {

  51.     private final List<T> pendingInsertions;
  52.     private final List<T> pendingDeletions;
  53.     private int skipped;

  54.     /** Handler to call when synchronized sequences are found. */
  55.     private final ReplacementsHandler<T> handler;

  56.     /**
  57.      * Simple constructor. Creates a new instance of {@link ReplacementsFinder}.
  58.      *
  59.      * @param handler  handler to call when synchronized sequences are found
  60.      */
  61.     public ReplacementsFinder(final ReplacementsHandler<T> handler) {
  62.         pendingInsertions = new ArrayList<>();
  63.         pendingDeletions = new ArrayList<>();
  64.         skipped = 0;
  65.         this.handler = handler;
  66.     }

  67.     /**
  68.      * Add an object to the pending deletions set.
  69.      *
  70.      * @param object  object to delete
  71.      */
  72.     @Override
  73.     public void visitDeleteCommand(final T object) {
  74.         pendingDeletions.add(object);
  75.     }

  76.     /**
  77.      * Add an object to the pending insertions set.
  78.      *
  79.      * @param object  object to insert
  80.      */
  81.     @Override
  82.     public void visitInsertCommand(final T object) {
  83.         pendingInsertions.add(object);
  84.     }

  85.     /**
  86.      * Handle a synchronization object.
  87.      * <p>
  88.      * When a synchronization object is identified, the pending insertions and
  89.      * pending deletions sets are provided to the user handler as subsequences.
  90.      *
  91.      * @param object  synchronization object detected
  92.      */
  93.     @Override
  94.     public void visitKeepCommand(final T object) {
  95.         if (pendingDeletions.isEmpty() && pendingInsertions.isEmpty()) {
  96.             ++skipped;
  97.         } else {
  98.             handler.handleReplacement(skipped, pendingDeletions, pendingInsertions);
  99.             pendingDeletions.clear();
  100.             pendingInsertions.clear();
  101.             skipped = 1;
  102.         }
  103.     }

  104. }