Merge "Remove SuggestionsGatherer."

main
Keisuke Kuroyanagi 2014-07-10 07:36:16 +00:00 committed by Android (Google) Code Review
commit b7ecb258dc
3 changed files with 67 additions and 98 deletions

View File

@ -155,6 +155,10 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
onSharedPreferenceChanged(prefs, PREF_USE_CONTACTS_KEY); onSharedPreferenceChanged(prefs, PREF_USE_CONTACTS_KEY);
} }
public float getRecommendedThreshold() {
return mRecommendedThreshold;
}
private static String getKeyboardLayoutNameForScript(final int script) { private static String getKeyboardLayoutNameForScript(final int script) {
switch (script) { switch (script) {
case ScriptUtils.SCRIPT_LATIN: case ScriptUtils.SCRIPT_LATIN:
@ -214,95 +218,6 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
EMPTY_STRING_ARRAY); 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) { public boolean isValidWord(final Locale locale, final String word) {
mSemaphore.acquireUninterruptibly(); mSemaphore.acquireUninterruptibly();
try { try {

View File

@ -32,7 +32,6 @@ import java.util.Locale;
public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheckerSession { public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheckerSession {
private static final String TAG = AndroidSpellCheckerSession.class.getSimpleName(); private static final String TAG = AndroidSpellCheckerSession.class.getSimpleName();
private static final boolean DBG = false; private static final boolean DBG = false;
private final static String[] EMPTY_STRING_ARRAY = new String[0];
private final Resources mResources; private final Resources mResources;
private SentenceLevelAdapter mSentenceLevelAdapter; private SentenceLevelAdapter mSentenceLevelAdapter;

View File

@ -34,20 +34,22 @@ import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.PrevWordsInfo; import com.android.inputmethod.latin.PrevWordsInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.WordComposer; import com.android.inputmethod.latin.WordComposer;
import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion; import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService.SuggestionsGatherer;
import com.android.inputmethod.latin.utils.CoordinateUtils; import com.android.inputmethod.latin.utils.CoordinateUtils;
import com.android.inputmethod.latin.utils.LocaleUtils; import com.android.inputmethod.latin.utils.LocaleUtils;
import com.android.inputmethod.latin.utils.ScriptUtils; import com.android.inputmethod.latin.utils.ScriptUtils;
import com.android.inputmethod.latin.utils.StringUtils; import com.android.inputmethod.latin.utils.StringUtils;
import com.android.inputmethod.latin.utils.SuggestionResults; import com.android.inputmethod.latin.utils.SuggestionResults;
import java.util.ArrayList;
import java.util.Locale; import java.util.Locale;
public abstract class AndroidWordLevelSpellCheckerSession extends Session { public abstract class AndroidWordLevelSpellCheckerSession extends Session {
private static final String TAG = AndroidWordLevelSpellCheckerSession.class.getSimpleName(); private static final String TAG = AndroidWordLevelSpellCheckerSession.class.getSimpleName();
private static final boolean DBG = false; private static final boolean DBG = false;
public final static String[] EMPTY_STRING_ARRAY = new String[0];
// Immutable, but not available in the constructor. // Immutable, but not available in the constructor.
private Locale mLocale; private Locale mLocale;
// Cache this for performance // Cache this for performance
@ -279,14 +281,11 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
proximityInfo = keyboard.getProximityInfo(); proximityInfo = keyboard.getProximityInfo();
} }
composer.setComposingWord(codePoints, coordinates); composer.setComposingWord(codePoints, coordinates);
// TODO: Don't gather suggestions if the limit is <= 0 unless necessary
final SuggestionResults suggestionResults = mService.getSuggestionResults( final SuggestionResults suggestionResults = mService.getSuggestionResults(
mLocale, composer, prevWordsInfo, proximityInfo); mLocale, composer, prevWordsInfo, proximityInfo);
// TODO: Don't gather suggestions if the limit is <= 0 unless necessary final Result result = getResult(capitalizeType, mLocale, suggestionsLimit,
final SuggestionsGatherer suggestionsGatherer = mService.newSuggestionsGatherer( mService.getRecommendedThreshold(), text, suggestionResults);
text, suggestionsLimit);
suggestionsGatherer.addResults(suggestionResults);
final SuggestionsGatherer.Result result = suggestionsGatherer.getResults(
capitalizeType, mLocale);
isInDict = isInDictForAnyCapitalization(text, capitalizeType); isInDict = isInDictForAnyCapitalization(text, capitalizeType);
if (DBG) { if (DBG) {
Log.i(TAG, "Spell checking results for " + text + " with suggestion limit " 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 * 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. * access the dictionary files, which the provider restricts to the identity of Latin IME.