From 0806bb01d9e857db9fbac38b9b6e77feb9e9e4c9 Mon Sep 17 00:00:00 2001 From: Tom Ouyang Date: Thu, 19 Apr 2012 10:54:37 -0700 Subject: [PATCH] Binary bigram lookup checks both uppercase and lowercase when previous word is uppercase. Bug: 6363029 Change-Id: I71a1ed5b88f54fcc15bfaf89d3645b8f17ebb821 --- .../inputmethod/latin/StringUtils.java | 17 ++++++++++ .../android/inputmethod/latin/Suggest.java | 34 +++++++++++-------- .../inputmethod/latin/StringUtilsTests.java | 11 ++++++ 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java index 160581cbe..a43b90525 100644 --- a/java/src/com/android/inputmethod/latin/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/StringUtils.java @@ -122,6 +122,23 @@ public class StringUtils { return true; } + /** + * Returns true if cs contains any upper case characters. + * + * @param cs the CharSequence to check + * @return {@code true} if cs contains any upper case characters, {@code false} otherwise. + */ + public static boolean hasUpperCase(final CharSequence cs) { + final int length = cs.length(); + for (int i = 0, cp = 0; i < length; i += Character.charCount(cp)) { + cp = Character.codePointAt(cs, i); + if (Character.isUpperCase(cp)) { + return true; + } + } + return false; + } + /** * Remove duplicates from an array of strings. * diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 86753e2cc..7cbee4f71 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -242,13 +242,8 @@ public class Suggest implements Dictionary.WordCallback { mBigramSuggestions = new ArrayList(PREF_MAX_BIGRAMS); - CharSequence lowerPrevWord = prevWordForBigram.toString().toLowerCase(); - if (mMainDict != null && mMainDict.isValidWord(lowerPrevWord)) { - prevWordForBigram = lowerPrevWord; - } - for (final Dictionary dictionary : mBigramDictionaries.values()) { - dictionary.getBigrams(sEmptyWordComposer, prevWordForBigram, this); - } + getAllBigrams(prevWordForBigram, sEmptyWordComposer); + // Nothing entered: return all bigrams for the previous word int insertCount = Math.min(mBigramSuggestions.size(), mPrefMaxSuggestions); for (int i = 0; i < insertCount; ++i) { @@ -290,13 +285,7 @@ public class Suggest implements Dictionary.WordCallback { mBigramSuggestions = new ArrayList(PREF_MAX_BIGRAMS); if (!TextUtils.isEmpty(prevWordForBigram)) { - CharSequence lowerPrevWord = prevWordForBigram.toString().toLowerCase(); - if (mMainDict != null && mMainDict.isValidWord(lowerPrevWord)) { - prevWordForBigram = lowerPrevWord; - } - for (final Dictionary dictionary : mBigramDictionaries.values()) { - dictionary.getBigrams(wordComposer, prevWordForBigram, this); - } + getAllBigrams(prevWordForBigram, wordComposer); if (TextUtils.isEmpty(consideredWord)) { // Nothing entered: return all bigrams for the previous word int insertCount = Math.min(mBigramSuggestions.size(), mPrefMaxSuggestions); @@ -409,6 +398,23 @@ public class Suggest implements Dictionary.WordCallback { false /* isObsoleteSuggestions */); } + /** + * 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 getSuggestionsInfoListWithDebugInfo( final String typedWord, final ArrayList suggestions) { final SuggestedWordInfo typedWordInfo = suggestions.get(0); diff --git a/tests/src/com/android/inputmethod/latin/StringUtilsTests.java b/tests/src/com/android/inputmethod/latin/StringUtilsTests.java index 8a5a82246..5db06ef51 100644 --- a/tests/src/com/android/inputmethod/latin/StringUtilsTests.java +++ b/tests/src/com/android/inputmethod/latin/StringUtilsTests.java @@ -88,4 +88,15 @@ public class StringUtilsTests extends AndroidTestCase { assertEquals("in 5 elements at position 2,4", "key1,key3,key5", StringUtils.removeFromCsvIfExists("key", "key1,key,key3,key,key5")); } + + public void testHasUpperCase() { + assertTrue("single upper-case string", StringUtils.hasUpperCase("String")); + assertTrue("multi upper-case string", StringUtils.hasUpperCase("stRInG")); + assertTrue("all upper-case string", StringUtils.hasUpperCase("STRING")); + assertTrue("upper-case string with non-letters", StringUtils.hasUpperCase("He's")); + + assertFalse("empty string", StringUtils.hasUpperCase("")); + assertFalse("lower-case string", StringUtils.hasUpperCase("string")); + assertFalse("lower-case string with non-letters", StringUtils.hasUpperCase("he's")); + } }