OpenWnnEngineEN.java revision 4ea4d400da5130039b3dd11ad0adfdd4e8cab0ff
1/* 2 * Copyright (C) 2008,2009 OMRON SOFTWARE Co., Ltd. 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 17package jp.co.omronsoft.openwnn.EN; 18 19import java.util.HashMap; 20import java.util.ArrayList; 21 22import jp.co.omronsoft.openwnn.*; 23import android.content.SharedPreferences; 24import android.util.Log; 25 26/** 27 * The OpenWnn engine class for English IME. 28 * 29 * @author Copyright (C) 2009 OMRON SOFTWARE CO., LTD. All Rights Reserved. 30 */ 31public class OpenWnnEngineEN implements WnnEngine { 32 /** Normal dictionary */ 33 public static final int DICT_DEFAULT = 0; 34 /** Dictionary for mistype correction */ 35 public static final int DICT_FOR_CORRECT_MISTYPE = 1; 36 /** Score(frequency value) of word in the learning dictionary */ 37 public static final int FREQ_LEARN = 600; 38 /** Score(frequency value) of word in the user dictionary */ 39 public static final int FREQ_USER = 500; 40 /** Limitation of predicted candidates */ 41 public static final int PREDICT_LIMIT = 300; 42 43 /** OpenWnn dictionary */ 44 private WnnDictionary mDictionary; 45 /** Word list */ 46 private ArrayList<WnnWord> mConvResult; 47 /** HashMap for checking duplicate word */ 48 private HashMap<String, WnnWord> mCandTable; 49 /** Input string */ 50 private String mInputString; 51 /** Searching string */ 52 private String mSearchKey; 53 /** Number of output candidates */ 54 private int mOutputNum; 55 /** The candidate filter */ 56 private CandidateFilter mFilter = null; 57 58 /** 59 * Candidate's case 60 * <br> 61 * CASE_LOWER: all letters are lower.<br> 62 * CASE_HEAD_UPPER: the first letter is upper; others are lower.<br> 63 * CASE_UPPER: all letters are upper.<br> 64 */ 65 private int mCandidateCase; 66 private static final int CASE_LOWER = 0; 67 private static final int CASE_UPPER = 1; 68 private static final int CASE_HEAD_UPPER = 3; 69 70 /** 71 * Constructor 72 * 73 * @param writableDictionaryName Writable dictionary file name(null if not use) 74 */ 75 public OpenWnnEngineEN(String writableDictionaryName) { 76 mConvResult = new ArrayList<WnnWord>(); 77 mCandTable = new HashMap<String, WnnWord>(); 78 mSearchKey = null; 79 mOutputNum = 0; 80 81 mDictionary = new OpenWnnDictionaryImpl( 82 "/data/data/jp.co.omronsoft.openwnn/lib/libWnnEngDic.so", 83 writableDictionaryName); 84 if (!mDictionary.isActive()) { 85 mDictionary = new OpenWnnDictionaryImpl( 86 "/system/lib/libWnnEngDic.so", 87 writableDictionaryName); 88 } 89 mDictionary.clearDictionary( ); 90 91 mDictionary.setDictionary(0, 400, 550); 92 mDictionary.setDictionary(1, 400, 550); 93 mDictionary.setDictionary(2, 400, 550); 94 mDictionary.setDictionary(WnnDictionary.INDEX_USER_DICTIONARY, FREQ_USER, FREQ_USER); 95 mDictionary.setDictionary(WnnDictionary.INDEX_LEARN_DICTIONARY, FREQ_LEARN, FREQ_LEARN); 96 97 mDictionary.setApproxPattern(WnnDictionary.APPROX_PATTERN_EN_QWERTY_NEAR); 98 99 mDictionary.setInUseState( false ); 100 } 101 102 /** 103 * Get a candidate. 104 * 105 * @param index Index of candidate 106 * @return A candidate; {@code null} if no candidate for the index. 107 */ 108 private WnnWord getCandidate(int index) { 109 WnnWord word; 110 /* search the candidate from the dictionaries */ 111 while (mConvResult.size() < PREDICT_LIMIT && index >= mConvResult.size()) { 112 while ((word = mDictionary.getNextWord()) != null) { 113 /* adjust the case of letter */ 114 char c = word.candidate.charAt(0); 115 if (mCandidateCase == CASE_LOWER) { 116 if (Character.isLowerCase(c)) { 117 break; 118 } 119 } else if (mCandidateCase == CASE_HEAD_UPPER) { 120 if (Character.isLowerCase(c)) { 121 word.candidate = Character.toString(Character.toUpperCase(c)) + word.candidate.substring(1); 122 } 123 break; 124 } else { 125 word.candidate = word.candidate.toUpperCase(); 126 break; 127 } 128 } 129 if (word == null) { 130 break; 131 } 132 /* check duplication */ 133 addCandidate(word); 134 } 135 136 /* get the default candidates */ 137 if (index >= mConvResult.size()) { 138 /* input string itself */ 139 addCandidate(new WnnWord(mInputString, mSearchKey)); 140 141 /* Capitalize the head of input */ 142 if (mSearchKey.length() > 1) { 143 addCandidate(new WnnWord(mSearchKey.substring(0,1).toUpperCase() + mSearchKey.substring(1), 144 mSearchKey)); 145 } 146 147 /* Capitalize all */ 148 addCandidate(new WnnWord(mSearchKey.toUpperCase(), mSearchKey)); 149 } 150 151 if (index >= mConvResult.size()) { 152 return null; 153 } 154 return mConvResult.get(index); 155 } 156 157 /** 158 * Add a word to the candidates list if there is no duplication. 159 * 160 * @param word A word 161 * @return {@code true} if the word is added to the list; {@code false} if not. 162 */ 163 private boolean addCandidate(WnnWord word) { 164 if (word.candidate == null || mCandTable.containsKey(word.candidate)) { 165 return false; 166 } 167 if (mFilter != null && !mFilter.isAllowed(word)) { 168 return false; 169 } 170 mCandTable.put(word.candidate, word); 171 mConvResult.add(word); 172 return true; 173 } 174 175 private void clearCandidates() { 176 mConvResult.clear(); 177 mCandTable.clear(); 178 mOutputNum = 0; 179 mSearchKey = null; 180 } 181 182 /** 183 * Set dictionary. 184 * 185 * @param type Type of dictionary (DIC_DEFAULT or DIC_FOR_CORRECT_MISTYPE) 186 * @return {@code true} if the dictionary is changed; {@code false} if not. 187 */ 188 public boolean setDictionary(int type) { 189 if (type == DICT_FOR_CORRECT_MISTYPE) { 190 mDictionary.clearApproxPattern(); 191 mDictionary.setApproxPattern(WnnDictionary.APPROX_PATTERN_EN_QWERTY_NEAR); 192 } else { 193 mDictionary.clearApproxPattern(); 194 } 195 return true; 196 } 197 198 /** 199 * Set search key for the dictionary. 200 * <br> 201 * To search the dictionary, this method set the lower case of 202 * input string to the search key. And hold the input string's 203 * capitalization information to adjust the candidates 204 * capitalization later. 205 * 206 * @param input Input string 207 * @return {@code true} if the search key is set; {@code false} if not. 208 */ 209 private boolean setSearchKey(String input) { 210 if (input.length() == 0) { 211 return false; 212 } 213 214 /* set mInputString */ 215 mInputString = input; 216 217 /* set mSearchKey */ 218 mSearchKey = input.toLowerCase(); 219 220 /* set mCandidateCase */ 221 if (Character.isUpperCase(input.charAt(0))) { 222 if (input.length() > 1 && Character.isUpperCase(input.charAt(1))) { 223 mCandidateCase = CASE_UPPER; 224 } else { 225 mCandidateCase = CASE_HEAD_UPPER; 226 } 227 } else { 228 mCandidateCase = CASE_LOWER; 229 } 230 231 return true; 232 } 233 234 /** 235 * Set the candidate filter 236 * 237 * @param filter The candidate filter 238 */ 239 public void setFilter(CandidateFilter filter) { 240 mFilter = filter; 241 } 242 243 /*********************************************************************** 244 * WnnEngine's interface 245 **********************************************************************/ 246 /** @see jp.co.omronsoft.openwnn.WnnEngine#init */ 247 public void init() {} 248 249 /** @see jp.co.omronsoft.openwnn.WnnEngine#close */ 250 public void close() {} 251 252 /** @see jp.co.omronsoft.openwnn.WnnEngine#predict */ 253 public int predict(ComposingText text, int minLen, int maxLen) { 254 clearCandidates(); 255 256 if (text == null) { return 0; } 257 258 String input = text.toString(2); 259 if (!setSearchKey(input)) { 260 return 0; 261 } 262 263 /* set dictionaries by the length of input */ 264 WnnDictionary dict = mDictionary; 265 dict.setInUseState( true ); 266 267 dict.clearDictionary(); 268 dict.setDictionary(0, 400, 550); 269 if (input.length() > 1) { 270 dict.setDictionary(1, 400, 550); 271 } 272 if (input.length() > 2) { 273 dict.setDictionary(2, 400, 550); 274 } 275 dict.setDictionary(WnnDictionary.INDEX_USER_DICTIONARY, FREQ_USER, FREQ_USER); 276 dict.setDictionary(WnnDictionary.INDEX_LEARN_DICTIONARY, FREQ_LEARN, FREQ_LEARN); 277 278 /* search dictionaries */ 279 dict.searchWord(WnnDictionary.SEARCH_PREFIX, WnnDictionary.ORDER_BY_FREQUENCY, mSearchKey); 280 return 1; 281 } 282 283 /** @see jp.co.omronsoft.openwnn.WnnEngine#convert */ 284 public int convert(ComposingText text) { 285 clearCandidates(); 286 return 0; 287 } 288 289 /** @see jp.co.omronsoft.openwnn.WnnEngine#searchWords */ 290 public int searchWords(String key) { 291 clearCandidates(); 292 return 0; 293 } 294 295 /** @see jp.co.omronsoft.openwnn.WnnEngine#searchWords */ 296 public int searchWords(WnnWord word) { 297 clearCandidates(); 298 return 0; 299 } 300 301 /** @see jp.co.omronsoft.openwnn.WnnEngine#getNextCandidate */ 302 public WnnWord getNextCandidate() { 303 if (mSearchKey == null) { 304 return null; 305 } 306 WnnWord word = getCandidate(mOutputNum); 307 if (word != null) { 308 mOutputNum++; 309 } 310 return word; 311 } 312 313 /** @see jp.co.omronsoft.openwnn.WnnEngine#learn */ 314 public boolean learn(WnnWord word) { 315 return ( mDictionary.learnWord(word) == 0 ); 316 } 317 318 /** @see jp.co.omronsoft.openwnn.WnnEngine#addWord */ 319 public int addWord(WnnWord word) { 320 WnnDictionary dict = mDictionary; 321 dict.setInUseState( true ); 322 dict.addWordToUserDictionary(word); 323 dict.setInUseState( false ); 324 return 0; 325 } 326 327 /** @see jp.co.omronsoft.openwnn.WnnEngine#deleteWord */ 328 public boolean deleteWord(WnnWord word) { 329 WnnDictionary dict = mDictionary; 330 dict.setInUseState( true ); 331 dict.removeWordFromUserDictionary(word); 332 dict.setInUseState( false ); 333 return false; 334 } 335 336 /** @see jp.co.omronsoft.openwnn.WnnEngine#setPreferences */ 337 public void setPreferences(SharedPreferences pref) {} 338 339 /** @see jp.co.omronsoft.openwnn.WnnEngine#breakSequence */ 340 public void breakSequence() {} 341 342 /** @see jp.co.omronsoft.openwnn.WnnEngine#makeCandidateListOf */ 343 public int makeCandidateListOf(int clausePosition) {return 0;} 344 345 /** @see jp.co.omronsoft.openwnn.WnnEngine#initializeDictionary */ 346 public boolean initializeDictionary(int dictionary) { 347 WnnDictionary dict = mDictionary; 348 349 switch( dictionary ) { 350 case WnnEngine.DICTIONARY_TYPE_LEARN: 351 dict.setInUseState( true ); 352 dict.clearLearnDictionary(); 353 dict.setInUseState( false ); 354 return true; 355 356 case WnnEngine.DICTIONARY_TYPE_USER: 357 dict.setInUseState( true ); 358 dict.clearUserDictionary(); 359 dict.setInUseState( false ); 360 return true; 361 } 362 return false; 363 } 364 365 /** @see jp.co.omronsoft.openwnn.WnnEngine#initializeDictionary */ 366 public boolean initializeDictionary(int dictionary, int type) { 367 return initializeDictionary(dictionary); 368 } 369 370 /** @see jp.co.omronsoft.openwnn.WnnEngine#getUserDictionaryWords */ 371 public WnnWord[] getUserDictionaryWords( ) { 372 WnnDictionary dict = mDictionary; 373 dict.setInUseState( true ); 374 WnnWord[] result = dict.getUserDictionaryWords( ); 375 dict.setInUseState( false ); 376 return result; 377 } 378 379} 380