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