From 8fd75b3147574ffbaf5ba6b383ed6fe42a32602d Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Tue, 31 May 2011 16:27:32 +0900 Subject: [PATCH] Add spell checking core methods. Bug: 4176026 Change-Id: Ic6ea3e084b3ebacfc5fd998d2c7b0130f7b0ec48 --- java/proguard.flags | 4 + .../latin/spellcheck/SpellChecker.java | 114 ++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 java/src/com/android/inputmethod/latin/spellcheck/SpellChecker.java diff --git a/java/proguard.flags b/java/proguard.flags index 914bd7595..9094be401 100644 --- a/java/proguard.flags +++ b/java/proguard.flags @@ -22,3 +22,7 @@ -keep class com.android.inputmethod.latin.Utils { boolean equalsIgnoreCase(...); } + +-keep class com.android.inputmethod.latin.spellcheck.SpellChecker { + *; +} diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellChecker.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellChecker.java new file mode 100644 index 000000000..e3407a269 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellChecker.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.android.inputmethod.latin.spellcheck; + +import android.content.Context; +import android.content.res.Resources; + +import com.android.inputmethod.latin.Dictionary; +import com.android.inputmethod.latin.Dictionary.DataType; +import com.android.inputmethod.latin.Dictionary.WordCallback; +import com.android.inputmethod.latin.DictionaryFactory; +import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.WordComposer; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; + +/** + * Implements spell checking methods. + */ +public class SpellChecker { + + public final Dictionary mDictionary; + + public SpellChecker(final Context context, final Locale locale) { + final Resources resources = context.getResources(); + final int fallbackResourceId = Utils.getMainDictionaryResourceId(resources); + mDictionary = DictionaryFactory.createDictionaryFromManager(context, locale, + fallbackResourceId); + } + + // Note : this must be reentrant + /** + * Finds out whether a word is in the dictionary or not. + * + * @param text the sequence containing the word to check for. + * @param start the index of the first character of the word in text. + * @param end the index of the next-to-last character in text. + * @return true if the word is in the dictionary, false otherwise. + */ + public boolean isCorrect(final CharSequence text, final int start, final int end) { + return mDictionary.isValidWord(text.subSequence(start, end)); + } + + private static class SuggestionsGatherer implements WordCallback { + private final int DEFAULT_SUGGESTION_LENGTH = 16; + private final List mSuggestions = new LinkedList(); + private int[] mScores = new int[DEFAULT_SUGGESTION_LENGTH]; + private int mLength = 0; + + synchronized public boolean addWord(char[] word, int wordOffset, int wordLength, int score, + int dicTypeId, DataType dataType) { + if (mLength >= mScores.length) { + final int newLength = mScores.length * 2; + mScores = new int[newLength]; + } + final int positionIndex = Arrays.binarySearch(mScores, 0, mLength, score); + // binarySearch returns the index if the element exists, and - - 1 + // if it doesn't. See documentation for binarySearch. + final int insertionIndex = positionIndex >= 0 ? positionIndex : -positionIndex - 1; + System.arraycopy(mScores, insertionIndex, mScores, insertionIndex + 1, + mLength - insertionIndex); + mLength += 1; + mScores[insertionIndex] = score; + mSuggestions.add(insertionIndex, new String(word, wordOffset, wordLength)); + return true; + } + + public List getGatheredSuggestions() { + return mSuggestions; + } + } + + // Note : this must be reentrant + /** + * Gets a list of suggestions for a specific string. + * + * This returns a list of possible corrections for the text passed as an + * arguments. It may split or group words, and even perform grammatical + * analysis. + * + * @param text the sequence containing the word to check for. + * @param start the index of the first character of the word in text. + * @param end the index of the next-to-last character in text. + * @return a list of possible suggestions to replace the text. + */ + public List getSuggestions(final CharSequence text, final int start, final int end) { + final SuggestionsGatherer suggestionsGatherer = new SuggestionsGatherer(); + final WordComposer composer = new WordComposer(); + for (int i = start; i < end; ++i) { + int character = text.charAt(i); + composer.add(character, new int[] { character }, + WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); + } + mDictionary.getWords(composer, suggestionsGatherer); + return suggestionsGatherer.getGatheredSuggestions(); + } +}