Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b7ecb258 authored by Keisuke Kuroyanagi's avatar Keisuke Kuroyanagi Committed by Android (Google) Code Review
Browse files

Merge "Remove SuggestionsGatherer."

parents 12e63799 1467fa0c
Loading
Loading
Loading
Loading
+4 −89
Original line number Diff line number Diff line
@@ -155,6 +155,10 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
        onSharedPreferenceChanged(prefs, PREF_USE_CONTACTS_KEY);
    }

    public float getRecommendedThreshold() {
        return mRecommendedThreshold;
    }

    private static String getKeyboardLayoutNameForScript(final int script) {
        switch (script) {
        case ScriptUtils.SCRIPT_LATIN:
@@ -214,95 +218,6 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
                EMPTY_STRING_ARRAY);
    }

    public SuggestionsGatherer newSuggestionsGatherer(final String text, int maxLength) {
        return new SuggestionsGatherer(text, mRecommendedThreshold, maxLength);
    }

    // TODO: remove this class and replace it by storage local to the session.
    public static final class SuggestionsGatherer {
        public static final class Result {
            public final String[] mSuggestions;
            public final boolean mHasRecommendedSuggestions;
            public Result(final String[] gatheredSuggestions,
                    final boolean hasRecommendedSuggestions) {
                mSuggestions = gatheredSuggestions;
                mHasRecommendedSuggestions = hasRecommendedSuggestions;
            }
        }

        private final ArrayList<String> mSuggestions;
        private final ArrayList<Integer> mScores;
        private final String mOriginalText;
        private final float mRecommendedThreshold;
        private final int mMaxLength;

        SuggestionsGatherer(final String originalText, final float recommendedThreshold,
                final int maxLength) {
            mOriginalText = originalText;
            mRecommendedThreshold = recommendedThreshold;
            mMaxLength = maxLength;
            mSuggestions = new ArrayList<>();
            mScores = new ArrayList<>();
        }

        public void addResults(final SuggestionResults suggestionResults) {
            if (suggestionResults == null) {
                return;
            }
            // suggestionResults is sorted.
            for (final SuggestedWordInfo suggestedWordInfo : suggestionResults) {
                mSuggestions.add(suggestedWordInfo.mWord);
                mScores.add(suggestedWordInfo.mScore);
            }
        }

        public Result getResults(final int capitalizeType, final Locale locale) {
            final String[] gatheredSuggestions;
            final boolean hasRecommendedSuggestions;
            if (mSuggestions.isEmpty()) {
                gatheredSuggestions = null;
                hasRecommendedSuggestions = false;
            } else {
                if (DBG) {
                    for (int i = 0; i < mSuggestions.size(); i++) {
                        Log.i(TAG, "" + mScores.get(i) + " " + mSuggestions.get(i));
                    }
                }
                StringUtils.removeDupes(mSuggestions);
                if (StringUtils.CAPITALIZE_ALL == capitalizeType) {
                    for (int i = 0; i < mSuggestions.size(); ++i) {
                        // get(i) returns a CharSequence which is actually a String so .toString()
                        // should return the same object.
                        mSuggestions.set(i, mSuggestions.get(i).toString().toUpperCase(locale));
                    }
                } else if (StringUtils.CAPITALIZE_FIRST == capitalizeType) {
                    for (int i = 0; i < mSuggestions.size(); ++i) {
                        // Likewise
                        mSuggestions.set(i, StringUtils.capitalizeFirstCodePoint(
                                mSuggestions.get(i).toString(), locale));
                    }
                }
                // This returns a String[], while toArray() returns an Object[] which cannot be cast
                // into a String[].
                gatheredSuggestions = mSuggestions.toArray(EMPTY_STRING_ARRAY);

                final int bestScore = mScores.get(0);
                final String bestSuggestion = mSuggestions.get(0);
                final float normalizedScore =
                        BinaryDictionaryUtils.calcNormalizedScore(
                                mOriginalText, bestSuggestion.toString(), bestScore);
                hasRecommendedSuggestions = (normalizedScore > mRecommendedThreshold);
                if (DBG) {
                    Log.i(TAG, "Best suggestion : " + bestSuggestion + ", score " + bestScore);
                    Log.i(TAG, "Normalized score = " + normalizedScore
                            + " (threshold " + mRecommendedThreshold
                            + ") => hasRecommendedSuggestions = " + hasRecommendedSuggestions);
                }
            }
            return new Result(gatheredSuggestions, hasRecommendedSuggestions);
        }
    }

    public boolean isValidWord(final Locale locale, final String word) {
        mSemaphore.acquireUninterruptibly();
        try {
+0 −1
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@ import java.util.Locale;
public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheckerSession {
    private static final String TAG = AndroidSpellCheckerSession.class.getSimpleName();
    private static final boolean DBG = false;
    private final static String[] EMPTY_STRING_ARRAY = new String[0];
    private final Resources mResources;
    private SentenceLevelAdapter mSentenceLevelAdapter;

+63 −8
Original line number Diff line number Diff line
@@ -34,20 +34,22 @@ import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.PrevWordsInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.WordComposer;
import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService.SuggestionsGatherer;
import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
import com.android.inputmethod.latin.utils.CoordinateUtils;
import com.android.inputmethod.latin.utils.LocaleUtils;
import com.android.inputmethod.latin.utils.ScriptUtils;
import com.android.inputmethod.latin.utils.StringUtils;
import com.android.inputmethod.latin.utils.SuggestionResults;

import java.util.ArrayList;
import java.util.Locale;

public abstract class AndroidWordLevelSpellCheckerSession extends Session {
    private static final String TAG = AndroidWordLevelSpellCheckerSession.class.getSimpleName();
    private static final boolean DBG = false;

    public final static String[] EMPTY_STRING_ARRAY = new String[0];

    // Immutable, but not available in the constructor.
    private Locale mLocale;
    // Cache this for performance
@@ -279,14 +281,11 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
                proximityInfo = keyboard.getProximityInfo();
            }
            composer.setComposingWord(codePoints, coordinates);
            // TODO: Don't gather suggestions if the limit is <= 0 unless necessary
            final SuggestionResults suggestionResults = mService.getSuggestionResults(
                    mLocale, composer, prevWordsInfo, proximityInfo);
            // TODO: Don't gather suggestions if the limit is <= 0 unless necessary
            final SuggestionsGatherer suggestionsGatherer = mService.newSuggestionsGatherer(
                    text, suggestionsLimit);
            suggestionsGatherer.addResults(suggestionResults);
            final SuggestionsGatherer.Result result = suggestionsGatherer.getResults(
                    capitalizeType, mLocale);
            final Result result = getResult(capitalizeType, mLocale, suggestionsLimit,
                    mService.getRecommendedThreshold(), text, suggestionResults);
            isInDict = isInDictForAnyCapitalization(text, capitalizeType);
            if (DBG) {
                Log.i(TAG, "Spell checking results for " + text + " with suggestion limit "
@@ -324,6 +323,62 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
        }
    }

    private static final class Result {
        public final String[] mSuggestions;
        public final boolean mHasRecommendedSuggestions;
        public Result(final String[] gatheredSuggestions,
                final boolean hasRecommendedSuggestions) {
            mSuggestions = gatheredSuggestions;
            mHasRecommendedSuggestions = hasRecommendedSuggestions;
        }
    }

    private static Result getResult(final int capitalizeType, final Locale locale,
            final int suggestionsLimit, final float recommendedThreshold, final String originalText,
            final SuggestionResults suggestionResults) {
        if (suggestionResults.isEmpty() || suggestionsLimit <= 0) {
            return new Result(null /* gatheredSuggestions */,
                    false /* hasRecommendedSuggestions */);
        }
        if (DBG) {
            for (final SuggestedWordInfo suggestedWordInfo : suggestionResults) {
                Log.i(TAG, "" + suggestedWordInfo.mScore + " " + suggestedWordInfo.mWord);
            }
        }
        final ArrayList<String> suggestions = new ArrayList<>();
        for (final SuggestedWordInfo suggestedWordInfo : suggestionResults) {
            final String suggestion;
            if (StringUtils.CAPITALIZE_ALL == capitalizeType) {
                suggestion = suggestedWordInfo.mWord.toUpperCase(locale);
            } else if (StringUtils.CAPITALIZE_FIRST == capitalizeType) {
                suggestion = StringUtils.capitalizeFirstCodePoint(
                        suggestedWordInfo.mWord, locale);
            } else {
                suggestion = suggestedWordInfo.mWord;
            }
            suggestions.add(suggestion);
        }
        StringUtils.removeDupes(suggestions);
        // This returns a String[], while toArray() returns an Object[] which cannot be cast
        // into a String[].
        final String[] gatheredSuggestions =
                suggestions.subList(0, Math.min(suggestions.size(), suggestionsLimit))
                        .toArray(EMPTY_STRING_ARRAY);

        final int bestScore = suggestionResults.first().mScore;
        final String bestSuggestion = suggestions.get(0);
        final float normalizedScore = BinaryDictionaryUtils.calcNormalizedScore(
                originalText, bestSuggestion.toString(), bestScore);
        final boolean hasRecommendedSuggestions = (normalizedScore > recommendedThreshold);
        if (DBG) {
            Log.i(TAG, "Best suggestion : " + bestSuggestion + ", score " + bestScore);
            Log.i(TAG, "Normalized score = " + normalizedScore
                    + " (threshold " + recommendedThreshold
                    + ") => hasRecommendedSuggestions = " + hasRecommendedSuggestions);
        }
        return new Result(gatheredSuggestions, hasRecommendedSuggestions);
    }

    /*
     * The spell checker acts on its own behalf. That is needed, in particular, to be able to
     * access the dictionary files, which the provider restricts to the identity of Latin IME.