001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.text.diff;
018
019import java.util.ArrayList;
020import java.util.List;
021
022/**
023 * This class gathers all the {@link EditCommand commands} needed to transform
024 * one objects sequence into another objects sequence.
025 * <p>
026 * An edit script is the most general view of the differences between two
027 * sequences. It is built as the result of the comparison between two sequences
028 * by the {@link StringsComparator StringsComparator} class. The user can
029 * walk through it using the <em>visitor</em> design pattern.
030 * </p>
031 * <p>
032 * It is guaranteed that the objects embedded in the {@link InsertCommand insert
033 * commands} come from the second sequence and that the objects embedded in
034 * either the {@link DeleteCommand delete commands} or {@link KeepCommand keep
035 * commands} come from the first sequence. This can be important if subclassing
036 * is used for some elements in the first sequence and the {@code equals}
037 * method is specialized.
038 * </p>
039 *
040 * @see StringsComparator
041 * @see EditCommand
042 * @see CommandVisitor
043 * @see ReplacementsHandler
044 *
045 * @param <T> object type
046 * @since 1.0
047 */
048public class EditScript<T> {
049
050    /** Container for the commands. */
051    private final List<EditCommand<T>> commands;
052
053    /** Length of the longest common subsequence. */
054    private int lcsLength;
055
056    /** Number of modifications. */
057    private int modifications;
058
059    /**
060     * Constructs a new empty script.
061     */
062    public EditScript() {
063        commands = new ArrayList<>();
064        lcsLength = 0;
065        modifications = 0;
066    }
067
068    /**
069     * Appends a delete command to the script.
070     *
071     * @param command  command to add
072     */
073    public void append(final DeleteCommand<T> command) {
074        commands.add(command);
075        ++modifications;
076    }
077
078    /**
079     * Appends an insert command to the script.
080     *
081     * @param command  command to add
082     */
083    public void append(final InsertCommand<T> command) {
084        commands.add(command);
085        ++modifications;
086    }
087
088    /**
089     * Appends a keep command to the script.
090     *
091     * @param command  command to add
092     */
093    public void append(final KeepCommand<T> command) {
094        commands.add(command);
095        ++lcsLength;
096    }
097
098    /**
099     * Gets the length of the Longest Common Subsequence (LCS). The length of the
100     * longest common subsequence is the number of {@link KeepCommand keep
101     * commands} in the script.
102     *
103     * @return length of the Longest Common Subsequence
104     */
105    public int getLCSLength() {
106        return lcsLength;
107    }
108
109    /**
110     * Gets the number of effective modifications. The number of effective
111     * modification is the number of {@link DeleteCommand delete} and
112     * {@link InsertCommand insert} commands in the script.
113     *
114     * @return number of effective modifications
115     */
116    public int getModifications() {
117        return modifications;
118    }
119
120    /**
121     * Visits the script. The script implements the <em>visitor</em> design
122     * pattern, this method is the entry point to which the user supplies its
123     * own visitor, the script will be responsible to drive it through the
124     * commands in order and call the appropriate method as each command is
125     * encountered.
126     *
127     * @param visitor  the visitor that will visit all commands in turn
128     */
129    public void visit(final CommandVisitor<T> visitor) {
130        commands.forEach(command -> command.accept(visitor));
131    }
132
133}