diff options
Diffstat (limited to 'java')
3 files changed, 67 insertions, 134 deletions
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 72b503138..90398deb2 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -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,118 +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 int[] mScores; - private final String mOriginalText; - private final float mRecommendedThreshold; - private final int mMaxLength; - private int mLength = 0; - - SuggestionsGatherer(final String originalText, final float recommendedThreshold, - final int maxLength) { - mOriginalText = originalText; - mRecommendedThreshold = recommendedThreshold; - mMaxLength = maxLength; - mSuggestions = new ArrayList<>(maxLength + 1); - mScores = new int[mMaxLength]; - } - - synchronized public boolean addWord(char[] word, int[] spaceIndices, int wordOffset, - int wordLength, int score) { - final int positionIndex = Arrays.binarySearch(mScores, 0, mLength, score); - // binarySearch returns the index if the element exists, and -<insertion index> - 1 - // if it doesn't. See documentation for binarySearch. - final int insertIndex = positionIndex >= 0 ? positionIndex : -positionIndex - 1; - - // Weak <- insertIndex == 0, ..., insertIndex == mLength -> Strong - if (insertIndex == 0 && mLength >= mMaxLength) { - return true; - } - - final String wordString = new String(word, wordOffset, wordLength); - if (mLength < mMaxLength) { - final int copyLen = mLength - insertIndex; - ++mLength; - System.arraycopy(mScores, insertIndex, mScores, insertIndex + 1, copyLen); - mSuggestions.add(insertIndex, wordString); - mScores[insertIndex] = score; - } else { - System.arraycopy(mScores, 1, mScores, 0, insertIndex - 1); - mSuggestions.add(insertIndex, wordString); - mSuggestions.remove(0); - mScores[insertIndex - 1] = score; - } - - return true; - } - - public Result getResults(final int capitalizeType, final Locale locale) { - final String[] gatheredSuggestions; - final boolean hasRecommendedSuggestions; - if (0 == mLength) { - gatheredSuggestions = null; - hasRecommendedSuggestions = false; - } else { - if (DBG) { - if (mLength != mSuggestions.size()) { - Log.e(TAG, "Suggestion size is not the same as stored mLength"); - } - for (int i = mLength - 1; i >= 0; --i) { - Log.i(TAG, "" + mScores[i] + " " + mSuggestions.get(i)); - } - } - Collections.reverse(mSuggestions); - 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[mLength - 1]; - 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 { diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java index 6bfd354ea..38d720664 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java @@ -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; diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java index 19c1dd0a5..d668672aa 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java @@ -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 @@ -259,14 +261,6 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { } final String text = inText.replaceAll( AndroidSpellCheckerService.APOSTROPHE, AndroidSpellCheckerService.SINGLE_QUOTE); - - // TODO: Don't gather suggestions if the limit is <= 0 unless necessary - //final SuggestionsGatherer suggestionsGatherer = new SuggestionsGatherer(text, - //mService.mSuggestionThreshold, mService.mRecommendedThreshold, - //suggestionsLimit); - final SuggestionsGatherer suggestionsGatherer = mService.newSuggestionsGatherer( - text, suggestionsLimit); - final int capitalizeType = StringUtils.getCapitalizationType(text); boolean isInDict = true; if (!mService.hasMainDictionaryForLocale(mLocale)) { @@ -287,20 +281,12 @@ 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); - if (suggestionResults != null) { - for (final SuggestedWordInfo suggestion : suggestionResults) { - final String suggestionStr = suggestion.mWord; - suggestionsGatherer.addWord(suggestionStr.toCharArray(), null, 0, - suggestionStr.length(), suggestion.mScore); - } - } + final Result result = getResult(capitalizeType, mLocale, suggestionsLimit, + mService.getRecommendedThreshold(), text, suggestionResults); isInDict = isInDictForAnyCapitalization(text, capitalizeType); - - final SuggestionsGatherer.Result result = suggestionsGatherer.getResults( - capitalizeType, mLocale); - if (DBG) { Log.i(TAG, "Spell checking results for " + text + " with suggestion limit " + suggestionsLimit); @@ -337,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. |