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