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.similarity;
018
019import org.apache.commons.lang3.Validate;
020
021/**
022 * This stores a {@link EditDistance} implementation and a {@link CharSequence} "left" string.
023 * The {@link #apply(CharSequence right)} method accepts the "right" string and invokes the
024 * comparison function for the pair of strings.
025 *
026 * <p>
027 * The following is an example which finds the most similar string:
028 * </p>
029 * <pre>
030 * EditDistance&lt;Integer&gt; editDistance = new LevenshteinDistance();
031 * String target = "Apache";
032 * EditDistanceFrom&lt;Integer&gt; editDistanceFrom =
033 *     new EditDistanceFrom&lt;Integer&gt;(editDistance, target);
034 * String mostSimilar = null;
035 * Integer shortestDistance = null;
036 *
037 * for (String test : new String[] { "Appaloosa", "a patchy", "apple" }) {
038 *     Integer distance = editDistanceFrom.apply(test);
039 *     if (shortestDistance == null || distance &lt; shortestDistance) {
040 *         shortestDistance = distance;
041 *         mostSimilar = test;
042 *     }
043 * }
044 *
045 * System.out.println("The string most similar to \"" + target + "\" "
046 *     + "is \"" + mostSimilar + "\" because "
047 *     + "its distance is only " + shortestDistance + ".");
048 * </pre>
049 *
050 * @param <R> This is the type of similarity score used by the EditDistance function.
051 * @since 1.0
052 */
053public class EditDistanceFrom<R> {
054
055    /**
056     * Edit distance.
057     */
058    private final EditDistance<R> editDistance;
059    /**
060     * Left parameter used in distance function.
061     */
062    private final CharSequence left;
063
064    /**
065     * This accepts the edit distance implementation and the "left" string.
066     *
067     * @param editDistance This may not be null.
068     * @param left This may be null here,
069     *             but the EditDistance#compare(CharSequence left, CharSequence right)
070     *             implementation may not accept nulls.
071     */
072    public EditDistanceFrom(final EditDistance<R> editDistance, final CharSequence left) {
073        Validate.isTrue(editDistance != null, "The edit distance may not be null.");
074
075        this.editDistance = editDistance;
076        this.left = left;
077    }
078
079    /**
080     * This compares "left" field against the "right" parameter
081     * using the "edit distance" implementation.
082     *
083     * @param right the second CharSequence
084     * @return The similarity score between two CharSequences
085     */
086    public R apply(final CharSequence right) {
087        return editDistance.apply(left, right);
088    }
089
090    /**
091     * Gets the edit distance.
092     *
093     * @return The edit distance
094     */
095    public EditDistance<R> getEditDistance() {
096        return editDistance;
097    }
098
099    /**
100     * Gets the left parameter.
101     *
102     * @return The left parameter
103     */
104    public CharSequence getLeft() {
105        return left;
106    }
107
108}