aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/Suggest.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin/Suggest.java')
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java177
1 files changed, 78 insertions, 99 deletions
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 61a8e2831..a4332936d 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -26,6 +26,7 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import java.io.File;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
@@ -34,7 +35,7 @@ import java.util.concurrent.ConcurrentHashMap;
* This class loads a dictionary and provides a list of suggestions for a given sequence of
* characters. This includes corrections and completions.
*/
-public class Suggest implements Dictionary.WordCallback {
+public class Suggest {
public static final String TAG = Suggest.class.getSimpleName();
public static final int APPROX_MAX_WORD_LENGTH = 32;
@@ -58,53 +59,61 @@ public class Suggest implements Dictionary.WordCallback {
public static final String DICT_KEY_CONTACTS = "contacts";
// User dictionary, the system-managed one.
public static final String DICT_KEY_USER = "user";
- // User history dictionary for the unigram map, internal to LatinIME
- public static final String DICT_KEY_USER_HISTORY_UNIGRAM = "history_unigram";
- // User history dictionary for the bigram map, internal to LatinIME
- public static final String DICT_KEY_USER_HISTORY_BIGRAM = "history_bigram";
+ // User history dictionary internal to LatinIME
+ public static final String DICT_KEY_USER_HISTORY = "history";
public static final String DICT_KEY_WHITELIST ="whitelist";
+ // TODO: remove this map. This only serves as backward compatibility with a feature
+ // that has never been used and has been broken for a while.
+ private static final HashMap<String, Integer> sDictKeyToDictIndex
+ = new HashMap<String, Integer>();
+ static {
+ sDictKeyToDictIndex.put(DICT_KEY_MAIN, DIC_MAIN);
+ sDictKeyToDictIndex.put(DICT_KEY_USER, DIC_USER);
+ sDictKeyToDictIndex.put(DICT_KEY_USER_HISTORY, DIC_USER_HISTORY);
+ sDictKeyToDictIndex.put(DICT_KEY_CONTACTS, DIC_CONTACTS);
+ sDictKeyToDictIndex.put(DICT_KEY_WHITELIST, DIC_WHITELIST);
+ }
private static final boolean DBG = LatinImeLogger.sDBG;
private Dictionary mMainDictionary;
private ContactsBinaryDictionary mContactsDict;
private WhitelistDictionary mWhiteListDictionary;
- private final ConcurrentHashMap<String, Dictionary> mUnigramDictionaries =
- new ConcurrentHashMap<String, Dictionary>();
- private final ConcurrentHashMap<String, Dictionary> mBigramDictionaries =
+ private final ConcurrentHashMap<String, Dictionary> mDictionaries =
new ConcurrentHashMap<String, Dictionary>();
public static final int MAX_SUGGESTIONS = 18;
private float mAutoCorrectionThreshold;
- private ArrayList<SuggestedWordInfo> mSuggestions = new ArrayList<SuggestedWordInfo>();
- private CharSequence mConsideredWord;
-
// TODO: Remove these member variables by passing more context to addWord() callback method
private boolean mIsFirstCharCapitalized;
private boolean mIsAllUpperCase;
private int mTrailingSingleQuotesCount;
+ // Locale used for upper- and title-casing words
+ final private Locale mLocale;
+
private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4;
public Suggest(final Context context, final Locale locale) {
initAsynchronously(context, locale);
+ mLocale = locale;
}
/* package for test */ Suggest(final Context context, final File dictionary,
final long startOffset, final long length, final Locale locale) {
final Dictionary mainDict = DictionaryFactory.createDictionaryForTest(context, dictionary,
startOffset, length /* useFullEditDistance */, false, locale);
+ mLocale = locale;
mMainDictionary = mainDict;
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, mainDict);
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, mainDict);
+ addOrReplaceDictionary(mDictionaries, DICT_KEY_MAIN, mainDict);
initWhitelistAndAutocorrectAndPool(context, locale);
}
private void initWhitelistAndAutocorrectAndPool(final Context context, final Locale locale) {
mWhiteListDictionary = new WhitelistDictionary(context, locale);
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_WHITELIST, mWhiteListDictionary);
+ addOrReplaceDictionary(mDictionaries, DICT_KEY_WHITELIST, mWhiteListDictionary);
}
private void initAsynchronously(final Context context, final Locale locale) {
@@ -133,8 +142,7 @@ public class Suggest implements Dictionary.WordCallback {
public void run() {
final DictionaryCollection newMainDict =
DictionaryFactory.createMainDictionaryFromManager(context, locale);
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, newMainDict);
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, newMainDict);
+ addOrReplaceDictionary(mDictionaries, DICT_KEY_MAIN, newMainDict);
mMainDictionary = newMainDict;
}
}.start();
@@ -155,7 +163,7 @@ public class Suggest implements Dictionary.WordCallback {
}
public ConcurrentHashMap<String, Dictionary> getUnigramDictionaries() {
- return mUnigramDictionaries;
+ return mDictionaries;
}
public static int getApproxMaxWordLength() {
@@ -167,7 +175,7 @@ public class Suggest implements Dictionary.WordCallback {
* before the main dictionary, if set. This refers to the system-managed user dictionary.
*/
public void setUserDictionary(UserBinaryDictionary userDictionary) {
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_USER, userDictionary);
+ addOrReplaceDictionary(mDictionaries, DICT_KEY_USER, userDictionary);
}
/**
@@ -177,15 +185,11 @@ public class Suggest implements Dictionary.WordCallback {
*/
public void setContactsDictionary(ContactsBinaryDictionary contactsDictionary) {
mContactsDict = contactsDictionary;
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_CONTACTS, contactsDictionary);
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_CONTACTS, contactsDictionary);
+ addOrReplaceDictionary(mDictionaries, DICT_KEY_CONTACTS, contactsDictionary);
}
public void setUserHistoryDictionary(UserHistoryDictionary userHistoryDictionary) {
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_USER_HISTORY_UNIGRAM,
- userHistoryDictionary);
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_USER_HISTORY_BIGRAM,
- userHistoryDictionary);
+ addOrReplaceDictionary(mDictionaries, DICT_KEY_USER_HISTORY, userHistoryDictionary);
}
public void setAutoCorrectionThreshold(float threshold) {
@@ -209,39 +213,6 @@ public class Suggest implements Dictionary.WordCallback {
return sb;
}
- private static final WordComposer sEmptyWordComposer = new WordComposer();
- public SuggestedWords getBigramPredictions(CharSequence prevWordForBigram) {
- LatinImeLogger.onStartSuggestion(prevWordForBigram);
- mIsFirstCharCapitalized = false;
- mIsAllUpperCase = false;
- mTrailingSingleQuotesCount = 0;
- mSuggestions = new ArrayList<SuggestedWordInfo>(MAX_SUGGESTIONS);
-
- // Treating USER_TYPED as UNIGRAM suggestion for logging now.
- LatinImeLogger.onAddSuggestedWord("", Suggest.DIC_USER_TYPED, Dictionary.UNIGRAM);
- mConsideredWord = "";
-
- getAllBigrams(prevWordForBigram, sEmptyWordComposer);
-
- SuggestedWordInfo.removeDups(mSuggestions);
-
- return new SuggestedWords(mSuggestions,
- false /* typedWordValid */,
- false /* hasAutoCorrectionCandidate */,
- false /* allowsToBeAutoCorrected */,
- false /* isPunctuationSuggestions */,
- false /* isObsoleteSuggestions */,
- true /* isPrediction */);
- }
-
- // Compatibility for tests. TODO: remove this
- public SuggestedWords getSuggestedWords(
- final WordComposer wordComposer, CharSequence prevWordForBigram,
- final ProximityInfo proximityInfo, final boolean isCorrectionEnabled) {
- return getSuggestedWords(wordComposer, prevWordForBigram, proximityInfo,
- isCorrectionEnabled, false);
- }
-
// TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder
public SuggestedWords getSuggestedWords(
final WordComposer wordComposer, CharSequence prevWordForBigram,
@@ -251,7 +222,8 @@ public class Suggest implements Dictionary.WordCallback {
mIsFirstCharCapitalized = !isPrediction && wordComposer.isFirstCharCapitalized();
mIsAllUpperCase = !isPrediction && wordComposer.isAllUpperCase();
mTrailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount();
- mSuggestions = new ArrayList<SuggestedWordInfo>(MAX_SUGGESTIONS);
+ final ArrayList<SuggestedWordInfo> suggestions =
+ new ArrayList<SuggestedWordInfo>(MAX_SUGGESTIONS);
final String typedWord = wordComposer.getTypedWord();
final String consideredWord = mTrailingSingleQuotesCount > 0
@@ -259,12 +231,32 @@ public class Suggest implements Dictionary.WordCallback {
: typedWord;
// Treating USER_TYPED as UNIGRAM suggestion for logging now.
LatinImeLogger.onAddSuggestedWord(typedWord, Suggest.DIC_USER_TYPED, Dictionary.UNIGRAM);
- mConsideredWord = consideredWord;
if (wordComposer.size() <= 1 && isCorrectionEnabled) {
// At first character typed, search only the bigrams
if (!TextUtils.isEmpty(prevWordForBigram)) {
- getAllBigrams(prevWordForBigram, wordComposer);
+ final CharSequence lowerPrevWord;
+ if (StringUtils.hasUpperCase(prevWordForBigram)) {
+ // TODO: Must pay attention to locale when changing case.
+ lowerPrevWord = prevWordForBigram.toString().toLowerCase();
+ } else {
+ lowerPrevWord = null;
+ }
+ for (final String key : mDictionaries.keySet()) {
+ final int dicTypeId = sDictKeyToDictIndex.get(key);
+ final Dictionary dictionary = mDictionaries.get(key);
+ final ArrayList<SuggestedWordInfo> localSuggestions =
+ dictionary.getBigrams(wordComposer, prevWordForBigram);
+ if (null != lowerPrevWord) {
+ localSuggestions.addAll(dictionary.getBigrams(wordComposer, lowerPrevWord));
+ }
+ for (final SuggestedWordInfo suggestion : localSuggestions) {
+ final String suggestionStr = suggestion.mWord.toString();
+ addWord(suggestionStr.toCharArray(), null, 0, suggestionStr.length(),
+ suggestion.mScore, dicTypeId, Dictionary.BIGRAM,
+ suggestions, consideredWord);
+ }
+ }
}
} else if (wordComposer.size() > 1) {
final WordComposer wordComposerForLookup;
@@ -277,12 +269,20 @@ public class Suggest implements Dictionary.WordCallback {
wordComposerForLookup = wordComposer;
}
// At second character typed, search the unigrams (scores being affected by bigrams)
- for (final String key : mUnigramDictionaries.keySet()) {
+ for (final String key : mDictionaries.keySet()) {
// Skip UserUnigramDictionary and WhitelistDictionary to lookup
- if (key.equals(DICT_KEY_USER_HISTORY_UNIGRAM) || key.equals(DICT_KEY_WHITELIST))
+ if (key.equals(DICT_KEY_USER_HISTORY) || key.equals(DICT_KEY_WHITELIST))
continue;
- final Dictionary dictionary = mUnigramDictionaries.get(key);
- dictionary.getWords(wordComposerForLookup, prevWordForBigram, this, proximityInfo);
+ final int dicTypeId = sDictKeyToDictIndex.get(key);
+ final Dictionary dictionary = mDictionaries.get(key);
+ final ArrayList<SuggestedWordInfo> localSuggestions = dictionary.getWords(
+ wordComposerForLookup, prevWordForBigram, proximityInfo);
+ for (final SuggestedWordInfo suggestion : localSuggestions) {
+ final String suggestionStr = suggestion.mWord.toString();
+ addWord(suggestionStr.toCharArray(), null, 0, suggestionStr.length(),
+ suggestion.mScore, dicTypeId, Dictionary.UNIGRAM,
+ suggestions, consideredWord);
+ }
}
}
@@ -292,8 +292,8 @@ public class Suggest implements Dictionary.WordCallback {
final boolean hasAutoCorrection;
if (isCorrectionEnabled) {
final CharSequence autoCorrection =
- AutoCorrection.computeAutoCorrectionWord(mUnigramDictionaries, wordComposer,
- mSuggestions, consideredWord, mAutoCorrectionThreshold,
+ AutoCorrection.computeAutoCorrectionWord(mDictionaries, wordComposer,
+ suggestions, consideredWord, mAutoCorrectionThreshold,
whitelistedWord);
hasAutoCorrection = (null != autoCorrection);
} else {
@@ -306,25 +306,25 @@ public class Suggest implements Dictionary.WordCallback {
for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) {
sb.appendCodePoint(Keyboard.CODE_SINGLE_QUOTE);
}
- mSuggestions.add(0, new SuggestedWordInfo(sb.toString(),
+ suggestions.add(0, new SuggestedWordInfo(sb.toString(),
SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_WHITELIST));
} else {
- mSuggestions.add(0, new SuggestedWordInfo(whitelistedWord,
+ suggestions.add(0, new SuggestedWordInfo(whitelistedWord,
SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_WHITELIST));
}
}
if (!isPrediction) {
- mSuggestions.add(0, new SuggestedWordInfo(typedWord, SuggestedWordInfo.MAX_SCORE,
+ suggestions.add(0, new SuggestedWordInfo(typedWord, SuggestedWordInfo.MAX_SCORE,
SuggestedWordInfo.KIND_TYPED));
}
- SuggestedWordInfo.removeDups(mSuggestions);
+ SuggestedWordInfo.removeDups(suggestions);
final ArrayList<SuggestedWordInfo> suggestionsList;
- if (DBG && !mSuggestions.isEmpty()) {
- suggestionsList = getSuggestionsInfoListWithDebugInfo(typedWord, mSuggestions);
+ if (DBG && !suggestions.isEmpty()) {
+ suggestionsList = getSuggestionsInfoListWithDebugInfo(typedWord, suggestions);
} else {
- suggestionsList = mSuggestions;
+ suggestionsList = suggestions;
}
// TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid"
@@ -362,23 +362,6 @@ public class Suggest implements Dictionary.WordCallback {
isPrediction);
}
- /**
- * Adds all bigram predictions for prevWord. Also checks the lower case version of prevWord if
- * it contains any upper case characters.
- */
- private void getAllBigrams(final CharSequence prevWord, final WordComposer wordComposer) {
- if (StringUtils.hasUpperCase(prevWord)) {
- // TODO: Must pay attention to locale when changing case.
- final CharSequence lowerPrevWord = prevWord.toString().toLowerCase();
- for (final Dictionary dictionary : mBigramDictionaries.values()) {
- dictionary.getBigrams(wordComposer, lowerPrevWord, this);
- }
- }
- for (final Dictionary dictionary : mBigramDictionaries.values()) {
- dictionary.getBigrams(wordComposer, prevWord, this);
- }
- }
-
private static ArrayList<SuggestedWordInfo> getSuggestionsInfoListWithDebugInfo(
final String typedWord, final ArrayList<SuggestedWordInfo> suggestions) {
final SuggestedWordInfo typedWordInfo = suggestions.get(0);
@@ -406,19 +389,16 @@ public class Suggest implements Dictionary.WordCallback {
}
// TODO: Use codepoint instead of char
- @Override
public boolean addWord(final char[] word, int[] indices, final int offset, final int length,
- int score, final int dicTypeId, final int dataType) {
+ int score, final int dicTypeId, final int dataType,
+ final ArrayList<SuggestedWordInfo> suggestions, final String consideredWord) {
int dataTypeForLog = dataType;
- final ArrayList<SuggestedWordInfo> suggestions;
- final int prefMaxSuggestions;
- suggestions = mSuggestions;
- prefMaxSuggestions = MAX_SUGGESTIONS;
+ final int prefMaxSuggestions = MAX_SUGGESTIONS;
int pos = 0;
// Check if it's the same word, only caps are different
- if (StringUtils.equalsIgnoreCase(mConsideredWord, word, offset, length)) {
+ if (StringUtils.equalsIgnoreCase(consideredWord, word, offset, length)) {
// TODO: remove this surrounding if clause and move this logic to
// getSuggestedWordBuilder.
if (suggestions.size() > 0) {
@@ -476,8 +456,7 @@ public class Suggest implements Dictionary.WordCallback {
public void close() {
final HashSet<Dictionary> dictionaries = new HashSet<Dictionary>();
- dictionaries.addAll(mUnigramDictionaries.values());
- dictionaries.addAll(mBigramDictionaries.values());
+ dictionaries.addAll(mDictionaries.values());
for (final Dictionary dictionary : dictionaries) {
dictionary.close();
}