Home | History | Annotate | Download | only in latin
      1 /*
      2  * Copyright (C) 2009 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 
     17 package com.android.inputmethod.latin;
     18 
     19 import android.content.ContentResolver;
     20 import android.content.Context;
     21 import android.database.ContentObserver;
     22 import android.database.Cursor;
     23 import android.os.SystemClock;
     24 import android.provider.BaseColumns;
     25 import android.provider.ContactsContract.Contacts;
     26 import android.text.TextUtils;
     27 import android.util.Log;
     28 
     29 import com.android.inputmethod.keyboard.Keyboard;
     30 
     31 // TODO: This class is superseded by {@link ContactsBinaryDictionary}. Should be cleaned up.
     32 /**
     33  * An expandable dictionary that stores the words from Contacts provider.
     34  *
     35  * @deprecated Use {@link ContactsBinaryDictionary}.
     36  */
     37 @Deprecated
     38 public class ContactsDictionary extends ExpandableDictionary {
     39 
     40     private static final String[] PROJECTION = {
     41         BaseColumns._ID,
     42         Contacts.DISPLAY_NAME,
     43     };
     44 
     45     private static final String TAG = "ContactsDictionary";
     46 
     47     /**
     48      * Frequency for contacts information into the dictionary
     49      */
     50     private static final int FREQUENCY_FOR_CONTACTS = 40;
     51     private static final int FREQUENCY_FOR_CONTACTS_BIGRAM = 90;
     52 
     53     private static final int INDEX_NAME = 1;
     54 
     55     private ContentObserver mObserver;
     56 
     57     private long mLastLoadedContacts;
     58 
     59     public ContactsDictionary(final Context context, final int dicTypeId) {
     60         super(context, dicTypeId);
     61         registerObserver(context);
     62         loadDictionary();
     63     }
     64 
     65     private synchronized void registerObserver(final Context context) {
     66         // Perform a managed query. The Activity will handle closing and requerying the cursor
     67         // when needed.
     68         if (mObserver != null) return;
     69         ContentResolver cres = context.getContentResolver();
     70         cres.registerContentObserver(
     71                 Contacts.CONTENT_URI, true, mObserver = new ContentObserver(null) {
     72                     @Override
     73                     public void onChange(boolean self) {
     74                         setRequiresReload(true);
     75                     }
     76                 });
     77     }
     78 
     79     public void reopen(final Context context) {
     80         registerObserver(context);
     81     }
     82 
     83     @Override
     84     public synchronized void close() {
     85         if (mObserver != null) {
     86             getContext().getContentResolver().unregisterContentObserver(mObserver);
     87             mObserver = null;
     88         }
     89         super.close();
     90     }
     91 
     92     @Override
     93     public void startDictionaryLoadingTaskLocked() {
     94         long now = SystemClock.uptimeMillis();
     95         if (mLastLoadedContacts == 0
     96                 || now - mLastLoadedContacts > 30 * 60 * 1000 /* 30 minutes */) {
     97             super.startDictionaryLoadingTaskLocked();
     98         }
     99     }
    100 
    101     @Override
    102     public void loadDictionaryAsync() {
    103         try {
    104             Cursor cursor = getContext().getContentResolver()
    105                     .query(Contacts.CONTENT_URI, PROJECTION, null, null, null);
    106             if (cursor != null) {
    107                 addWords(cursor);
    108             }
    109         } catch(IllegalStateException e) {
    110             Log.e(TAG, "Contacts DB is having problems");
    111         }
    112         mLastLoadedContacts = SystemClock.uptimeMillis();
    113     }
    114 
    115     @Override
    116     public void getBigrams(final WordComposer codes, final CharSequence previousWord,
    117             final WordCallback callback) {
    118         // Do not return bigrams from Contacts when nothing was typed.
    119         if (codes.size() <= 0) return;
    120         super.getBigrams(codes, previousWord, callback);
    121     }
    122 
    123     private void addWords(Cursor cursor) {
    124         clearDictionary();
    125 
    126         final int maxWordLength = getMaxWordLength();
    127         try {
    128             if (cursor.moveToFirst()) {
    129                 while (!cursor.isAfterLast()) {
    130                     String name = cursor.getString(INDEX_NAME);
    131 
    132                     if (name != null && -1 == name.indexOf('@')) {
    133                         int len = name.length();
    134                         String prevWord = null;
    135 
    136                         // TODO: Better tokenization for non-Latin writing systems
    137                         for (int i = 0; i < len; i++) {
    138                             if (Character.isLetter(name.charAt(i))) {
    139                                 int j;
    140                                 for (j = i + 1; j < len; j++) {
    141                                     char c = name.charAt(j);
    142 
    143                                     if (!(c == Keyboard.CODE_DASH
    144                                             || c == Keyboard.CODE_SINGLE_QUOTE
    145                                             || Character.isLetter(c))) {
    146                                         break;
    147                                     }
    148                                 }
    149 
    150                                 String word = name.substring(i, j);
    151                                 i = j - 1;
    152 
    153                                 // Safeguard against adding really long words. Stack
    154                                 // may overflow due to recursion
    155                                 // Also don't add single letter words, possibly confuses
    156                                 // capitalization of i.
    157                                 final int wordLen = word.length();
    158                                 if (wordLen < maxWordLength && wordLen > 1) {
    159                                     super.addWord(word, null /* shortcut */,
    160                                             FREQUENCY_FOR_CONTACTS);
    161                                     if (!TextUtils.isEmpty(prevWord)) {
    162                                         super.setBigramAndGetFrequency(prevWord, word,
    163                                                 FREQUENCY_FOR_CONTACTS_BIGRAM);
    164                                     }
    165                                     prevWord = word;
    166                                 }
    167                             }
    168                         }
    169                     }
    170                     cursor.moveToNext();
    171                 }
    172             }
    173             cursor.close();
    174         } catch(IllegalStateException e) {
    175             Log.e(TAG, "Contacts DB is having problems");
    176         }
    177     }
    178 }
    179