private boolean haveSufficientCommonality(String original, CharSequence suggestion) { final int originalLength = original.length(); final int suggestionLength = suggestion.length(); final int minLength = Math.min(originalLength, suggestionLength); if (minLength <= 2) return true; int matching = 0; int lessMatching = 0; // Count matches if we skip one character int i; for (i = 0; i < minLength; i++) { final char origChar = ExpandableDictionary.toLowerCase(original.charAt(i)); if (origChar == ExpandableDictionary.toLowerCase(suggestion.charAt(i))) { matching++; lessMatching++; } else if (i + 1 < suggestionLength && origChar == ExpandableDictionary.toLowerCase(suggestion.charAt(i + 1))) { lessMatching++; } } matching = Math.max(matching, lessMatching); if (minLength <= 4) { return matching >= 2; } else { return matching > minLength / 2; } }
/** * Adds a word to the dictionary and makes it persistent. * * @param word the word to add. If the word is capitalized, then the dictionary will recognize it * as a capitalized word when searched. * @param frequency the frequency of occurrence of the word. A frequency of 255 is considered the * highest. @TODO use a higher or float range for frequency */ @Override public synchronized void addWord(String word, int frequency) { // Force load the dictionary here synchronously if (getRequiresReload()) loadDictionaryAsync(); // Safeguard against adding long words. Can cause stack overflow. if (word.length() >= getMaxWordLength()) return; super.addWord(word, frequency); // Update the user dictionary provider final ContentValues values = new ContentValues(5); values.put(Words.WORD, word); values.put(Words.FREQUENCY, frequency); values.put(Words.LOCALE, mLocale); values.put(Words.APP_ID, 0); final ContentResolver contentResolver = getContext().getContentResolver(); new Thread("addWord") { public void run() { contentResolver.insert(Words.CONTENT_URI, values); } }.start(); // In case the above does a synchronous callback of the change observer setRequiresReload(false); }
@Override public void loadDictionaryAsync() { // Load the words that correspond to the current input locale Cursor cursor = query(MAIN_COLUMN_LOCALE + "=?", new String[] {mLocale}); try { if (cursor.moveToFirst()) { int word1Index = cursor.getColumnIndex(MAIN_COLUMN_WORD1); int word2Index = cursor.getColumnIndex(MAIN_COLUMN_WORD2); int frequencyIndex = cursor.getColumnIndex(FREQ_COLUMN_FREQUENCY); while (!cursor.isAfterLast()) { String word1 = cursor.getString(word1Index); String word2 = cursor.getString(word2Index); int frequency = cursor.getInt(frequencyIndex); // Safeguard against adding really long words. Stack may overflow due // to recursive lookup if (word1.length() < MAX_WORD_LENGTH && word2.length() < MAX_WORD_LENGTH) { super.setBigram(word1, word2, frequency); } cursor.moveToNext(); } } } finally { cursor.close(); } }
@Override public synchronized void close() { if (mObserver != null) { getContext().getContentResolver().unregisterContentObserver(mObserver); mObserver = null; } super.close(); }
@Override public void close() { flushPendingWrites(); // Don't close the database as locale changes will require it to be reopened anyway // Also, the database is written to somewhat frequently, so it needs to be kept alive // throughout the life of the process. // mOpenHelper.close(); super.close(); }
@Override public synchronized void getWords(final WordComposer codes, final WordCallback callback) { synchronized (mUpdatingLock) { // If we need to update, start off a background task if (mRequiresReload) loadDictionaryAsyncLocked(); // Currently updating contacts, don't return any results. if (mUpdatingContacts) return; } super.getWords(codes, callback); }
private void addWords(Cursor cursor) { clearDictionary(); final int maxWordLength = getMaxWordLength(); if (cursor.moveToFirst()) { while (!cursor.isAfterLast()) { String word = cursor.getString(INDEX_WORD); int frequency = cursor.getInt(INDEX_FREQUENCY); // Safeguard against adding really long words. Stack may overflow due // to recursion if (word.length() < maxWordLength) { super.addWord(word, frequency); } cursor.moveToNext(); } } cursor.close(); }
private void addWords(Cursor cursor) { clearDictionary(); final int maxWordLength = getMaxWordLength(); if (cursor.moveToFirst()) { while (!cursor.isAfterLast()) { String name = cursor.getString(INDEX_NAME); if (name != null) { int len = name.length(); // TODO: Better tokenization for non-Latin writing systems for (int i = 0; i < len; i++) { if (Character.isLetter(name.charAt(i))) { int j; for (j = i + 1; j < len; j++) { char c = name.charAt(j); if (!(c == '-' || c == '\'' || Character.isLetter(c))) { break; } } String word = name.substring(i, j); i = j - 1; // Safeguard against adding really long words. Stack // may overflow due to recursion // Also don't add single letter words, possibly confuses // capitalization of i. final int wordLen = word.length(); if (wordLen < maxWordLength && wordLen > 1) { super.addWord(word, 128); } } } } cursor.moveToNext(); } } cursor.close(); }
@Override public synchronized void getWords( final WordComposer codes, final WordCallback callback, int[] nextLettersFrequencies) { super.getWords(codes, callback, nextLettersFrequencies); }