Loading java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +4 −89 Original line number Diff line number Diff line Loading @@ -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: Loading Loading @@ -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 { Loading java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java +0 −1 Original line number Diff line number Diff line Loading @@ -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; Loading java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java +63 −8 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 " Loading Loading @@ -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. Loading Loading
java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +4 −89 Original line number Diff line number Diff line Loading @@ -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: Loading Loading @@ -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 { Loading
java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java +0 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java +63 −8 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 " Loading Loading @@ -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. Loading