1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package com.android.inputmethod.latin; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.text.TextUtils; 22 import android.util.Log; 23 import android.util.Pair; 24 25 import com.android.inputmethod.latin.LocaleUtils.RunInLocale; 26 27 import java.util.HashMap; 28 import java.util.Locale; 29 30 public class WhitelistDictionary extends ExpandableDictionary { 31 32 private static final boolean DBG = LatinImeLogger.sDBG; 33 private static final String TAG = WhitelistDictionary.class.getSimpleName(); 34 35 private final HashMap<String, Pair<Integer, String>> mWhitelistWords = 36 new HashMap<String, Pair<Integer, String>>(); 37 38 // TODO: Conform to the async load contact of ExpandableDictionary 39 public WhitelistDictionary(final Context context, final Locale locale) { 40 super(context, Suggest.DIC_WHITELIST); 41 // TODO: Move whitelist dictionary into main dictionary. 42 final RunInLocale<Void> job = new RunInLocale<Void>() { 43 @Override 44 protected Void job(Resources res) { 45 initWordlist(res.getStringArray(R.array.wordlist_whitelist)); 46 return null; 47 } 48 }; 49 job.runInLocale(context.getResources(), locale); 50 } 51 52 private void initWordlist(String[] wordlist) { 53 mWhitelistWords.clear(); 54 final int N = wordlist.length; 55 if (N % 3 != 0) { 56 if (DBG) { 57 Log.d(TAG, "The number of the whitelist is invalid."); 58 } 59 return; 60 } 61 try { 62 for (int i = 0; i < N; i += 3) { 63 final int score = Integer.valueOf(wordlist[i]); 64 final String before = wordlist[i + 1]; 65 final String after = wordlist[i + 2]; 66 if (before != null && after != null) { 67 mWhitelistWords.put( 68 before.toLowerCase(), new Pair<Integer, String>(score, after)); 69 addWord(after, null /* shortcut */, score); 70 } 71 } 72 } catch (NumberFormatException e) { 73 if (DBG) { 74 Log.d(TAG, "The score of the word is invalid."); 75 } 76 } 77 } 78 79 public String getWhitelistedWord(String before) { 80 if (before == null) return null; 81 final String lowerCaseBefore = before.toLowerCase(); 82 if(mWhitelistWords.containsKey(lowerCaseBefore)) { 83 if (DBG) { 84 Log.d(TAG, "--- found whitelistedWord: " + lowerCaseBefore); 85 } 86 return mWhitelistWords.get(lowerCaseBefore).second; 87 } 88 return null; 89 } 90 91 // See LatinIME#updateSuggestions. This breaks in the (queer) case that the whitelist 92 // lists that word a should autocorrect to word b, and word c would autocorrect to 93 // an upper-cased version of a. In this case, the way this return value is used would 94 // remove the first candidate when the user typed the upper-cased version of A. 95 // Example : abc -> def and xyz -> Abc 96 // A user typing Abc would experience it being autocorrected to something else (not 97 // necessarily def). 98 // There is no such combination in the whitelist at the time and there probably won't 99 // ever be - it doesn't make sense. But still. 100 public boolean shouldForciblyAutoCorrectFrom(CharSequence word) { 101 if (TextUtils.isEmpty(word)) return false; 102 final String correction = getWhitelistedWord(word.toString()); 103 if (TextUtils.isEmpty(correction)) return false; 104 return !correction.equals(word); 105 } 106 107 // Leave implementation of getWords and isValidWord to the superclass. 108 // The words have been added to the ExpandableDictionary with addWord() inside initWordlist. 109 } 110