/ime/latinime/src/com/googlecode/eyesfree/inputmethod/latin/UserDictionary.java

http://eyes-free.googlecode.com/ · Java · 143 lines · 91 code · 21 blank · 31 comment · 9 complexity · 2afbc20b16dd6bc4c5745007c4d4b612 MD5 · raw file

  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.googlecode.eyesfree.inputmethod.latin;
  17. import android.content.ContentResolver;
  18. import android.content.ContentValues;
  19. import android.content.Context;
  20. import android.database.ContentObserver;
  21. import android.database.Cursor;
  22. import android.provider.UserDictionary.Words;
  23. public class UserDictionary extends ExpandableDictionary {
  24. private static final String[] PROJECTION = {
  25. Words._ID,
  26. Words.WORD,
  27. Words.FREQUENCY
  28. };
  29. private static final int INDEX_WORD = 1;
  30. private static final int INDEX_FREQUENCY = 2;
  31. private ContentObserver mObserver;
  32. private String mLocale;
  33. public UserDictionary(Context context, String locale) {
  34. super(context, Suggest.DIC_USER);
  35. mLocale = locale;
  36. // Perform a managed query. The Activity will handle closing and requerying the cursor
  37. // when needed.
  38. ContentResolver cres = context.getContentResolver();
  39. cres.registerContentObserver(Words.CONTENT_URI, true, mObserver = new ContentObserver(null) {
  40. @Override
  41. public void onChange(boolean self) {
  42. setRequiresReload(true);
  43. }
  44. });
  45. loadDictionary();
  46. }
  47. @Override
  48. public synchronized void close() {
  49. if (mObserver != null) {
  50. getContext().getContentResolver().unregisterContentObserver(mObserver);
  51. mObserver = null;
  52. }
  53. super.close();
  54. }
  55. @Override
  56. public void loadDictionaryAsync() {
  57. Cursor cursor = getContext().getContentResolver()
  58. .query(Words.CONTENT_URI, PROJECTION, "(locale IS NULL) or (locale=?)",
  59. new String[] { mLocale }, null);
  60. addWords(cursor);
  61. }
  62. /**
  63. * Adds a word to the dictionary and makes it persistent.
  64. * @param word the word to add. If the word is capitalized, then the dictionary will
  65. * recognize it as a capitalized word when searched.
  66. * @param frequency the frequency of occurrence of the word. A frequency of 255 is considered
  67. * the highest.
  68. * @TODO use a higher or float range for frequency
  69. */
  70. @Override
  71. public synchronized void addWord(String word, int frequency) {
  72. // Force load the dictionary here synchronously
  73. if (getRequiresReload()) loadDictionaryAsync();
  74. // Safeguard against adding long words. Can cause stack overflow.
  75. if (word.length() >= getMaxWordLength()) return;
  76. super.addWord(word, frequency);
  77. // Update the user dictionary provider
  78. final ContentValues values = new ContentValues(5);
  79. values.put(Words.WORD, word);
  80. values.put(Words.FREQUENCY, frequency);
  81. values.put(Words.LOCALE, mLocale);
  82. values.put(Words.APP_ID, 0);
  83. final ContentResolver contentResolver = getContext().getContentResolver();
  84. new Thread("addWord") {
  85. @Override
  86. public void run() {
  87. contentResolver.insert(Words.CONTENT_URI, values);
  88. }
  89. }.start();
  90. // In case the above does a synchronous callback of the change observer
  91. setRequiresReload(false);
  92. }
  93. @Override
  94. public synchronized void getWords(final WordComposer codes, final WordCallback callback,
  95. int[] nextLettersFrequencies) {
  96. super.getWords(codes, callback, nextLettersFrequencies);
  97. }
  98. @Override
  99. public synchronized boolean isValidWord(CharSequence word) {
  100. return super.isValidWord(word);
  101. }
  102. private void addWords(Cursor cursor) {
  103. if (cursor == null) {
  104. return;
  105. }
  106. clearDictionary();
  107. final int maxWordLength = getMaxWordLength();
  108. if (cursor.moveToFirst()) {
  109. while (!cursor.isAfterLast()) {
  110. String word = cursor.getString(INDEX_WORD);
  111. int frequency = cursor.getInt(INDEX_FREQUENCY);
  112. // Safeguard against adding really long words. Stack may overflow due
  113. // to recursion
  114. if (word.length() < maxWordLength) {
  115. super.addWord(word, frequency);
  116. }
  117. cursor.moveToNext();
  118. }
  119. }
  120. cursor.close();
  121. }
  122. }