/* * Copyright (C) 2008-2012 OMRON SOFTWARE Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jp.co.omronsoft.openwnn.EN; import java.util.HashMap; import java.util.ArrayList; import jp.co.omronsoft.openwnn.*; import android.content.SharedPreferences; /** * The OpenWnn engine class for English IME. * * @author Copyright (C) 2009 OMRON SOFTWARE CO., LTD. All Rights Reserved. */ public class OpenWnnEngineEN implements WnnEngine { /** Normal dictionary */ public static final int DICT_DEFAULT = 0; /** Dictionary for mistype correction */ public static final int DICT_FOR_CORRECT_MISTYPE = 1; /** Score(frequency value) of word in the learning dictionary */ public static final int FREQ_LEARN = 600; /** Score(frequency value) of word in the user dictionary */ public static final int FREQ_USER = 500; /** Limitation of predicted candidates */ public static final int PREDICT_LIMIT = 300; /** OpenWnn dictionary */ private WnnDictionary mDictionary; /** Word list */ private ArrayList<WnnWord> mConvResult; /** HashMap for checking duplicate word */ private HashMap<String, WnnWord> mCandTable; /** Input string */ private String mInputString; /** Searching string */ private String mSearchKey; /** Number of output candidates */ private int mOutputNum; /** The candidate filter */ private CandidateFilter mFilter = null; /** * Candidate's case * <br> * CASE_LOWER: all letters are lower.<br> * CASE_HEAD_UPPER: the first letter is upper; others are lower.<br> * CASE_UPPER: all letters are upper.<br> */ private int mCandidateCase; private static final int CASE_LOWER = 0; private static final int CASE_UPPER = 1; private static final int CASE_HEAD_UPPER = 3; /** * Constructor * * @param writableDictionaryName Writable dictionary file name(null if not use) */ public OpenWnnEngineEN(String writableDictionaryName) { mConvResult = new ArrayList<WnnWord>(); mCandTable = new HashMap<String, WnnWord>(); mSearchKey = null; mOutputNum = 0; mDictionary = new OpenWnnDictionaryImpl( "/data/data/jp.co.omronsoft.openwnn/lib/libWnnEngDic.so", writableDictionaryName); if (!mDictionary.isActive()) { mDictionary = new OpenWnnDictionaryImpl( "/system/lib/libWnnEngDic.so", writableDictionaryName); } mDictionary.clearDictionary( ); mDictionary.setDictionary(0, 400, 550); mDictionary.setDictionary(1, 400, 550); mDictionary.setDictionary(2, 400, 550); mDictionary.setDictionary(WnnDictionary.INDEX_USER_DICTIONARY, FREQ_USER, FREQ_USER); mDictionary.setDictionary(WnnDictionary.INDEX_LEARN_DICTIONARY, FREQ_LEARN, FREQ_LEARN); mDictionary.setApproxPattern(WnnDictionary.APPROX_PATTERN_EN_QWERTY_NEAR); mDictionary.setInUseState( false ); } /** * Get a candidate. * * @param index Index of candidate * @return A candidate; {@code null} if no candidate for the index. */ private WnnWord getCandidate(int index) { WnnWord word; /* search the candidate from the dictionaries */ while (mConvResult.size() < PREDICT_LIMIT && index >= mConvResult.size()) { while ((word = mDictionary.getNextWord()) != null) { /* adjust the case of letter */ char c = word.candidate.charAt(0); if (mCandidateCase == CASE_LOWER) { if (Character.isLowerCase(c)) { break; } } else if (mCandidateCase == CASE_HEAD_UPPER) { if (Character.isLowerCase(c)) { word.candidate = Character.toString(Character.toUpperCase(c)) + word.candidate.substring(1); } break; } else { word.candidate = word.candidate.toUpperCase(); break; } } if (word == null) { break; } /* check duplication */ addCandidate(word); } /* get the default candidates */ if (index >= mConvResult.size()) { /* input string itself */ addCandidate(new WnnWord(mInputString, mSearchKey)); /* Capitalize the head of input */ if (mSearchKey.length() > 1) { addCandidate(new WnnWord(mSearchKey.substring(0,1).toUpperCase() + mSearchKey.substring(1), mSearchKey)); } /* Capitalize all */ addCandidate(new WnnWord(mSearchKey.toUpperCase(), mSearchKey)); } if (index >= mConvResult.size()) { return null; } return mConvResult.get(index); } /** * Add a word to the candidates list if there is no duplication. * * @param word A word * @return {@code true} if the word is added to the list; {@code false} if not. */ private boolean addCandidate(WnnWord word) { if (word.candidate == null || mCandTable.containsKey(word.candidate)) { return false; } if (mFilter != null && !mFilter.isAllowed(word)) { return false; } mCandTable.put(word.candidate, word); mConvResult.add(word); return true; } private void clearCandidates() { mConvResult.clear(); mCandTable.clear(); mOutputNum = 0; mSearchKey = null; } /** * Set dictionary. * * @param type Type of dictionary (DIC_DEFAULT or DIC_FOR_CORRECT_MISTYPE) * @return {@code true} if the dictionary is changed; {@code false} if not. */ public boolean setDictionary(int type) { if (type == DICT_FOR_CORRECT_MISTYPE) { mDictionary.clearApproxPattern(); mDictionary.setApproxPattern(WnnDictionary.APPROX_PATTERN_EN_QWERTY_NEAR); } else { mDictionary.clearApproxPattern(); } return true; } /** * Set search key for the dictionary. * <br> * To search the dictionary, this method set the lower case of * input string to the search key. And hold the input string's * capitalization information to adjust the candidates * capitalization later. * * @param input Input string * @return {@code true} if the search key is set; {@code false} if not. */ private boolean setSearchKey(String input) { if (input.length() == 0) { return false; } /* set mInputString */ mInputString = input; /* set mSearchKey */ mSearchKey = input.toLowerCase(); /* set mCandidateCase */ if (Character.isUpperCase(input.charAt(0))) { if (input.length() > 1 && Character.isUpperCase(input.charAt(1))) { mCandidateCase = CASE_UPPER; } else { mCandidateCase = CASE_HEAD_UPPER; } } else { mCandidateCase = CASE_LOWER; } return true; } /** * Set the candidate filter * * @param filter The candidate filter */ public void setFilter(CandidateFilter filter) { mFilter = filter; } /*********************************************************************** * WnnEngine's interface **********************************************************************/ /** @see jp.co.omronsoft.openwnn.WnnEngine#init */ public void init() {} /** @see jp.co.omronsoft.openwnn.WnnEngine#close */ public void close() {} /** @see jp.co.omronsoft.openwnn.WnnEngine#predict */ public int predict(ComposingText text, int minLen, int maxLen) { clearCandidates(); if (text == null) { return 0; } String input = text.toString(2); if (!setSearchKey(input)) { return 0; } /* set dictionaries by the length of input */ WnnDictionary dict = mDictionary; dict.setInUseState( true ); dict.clearDictionary(); dict.setDictionary(0, 400, 550); if (input.length() > 1) { dict.setDictionary(1, 400, 550); } if (input.length() > 2) { dict.setDictionary(2, 400, 550); } dict.setDictionary(WnnDictionary.INDEX_USER_DICTIONARY, FREQ_USER, FREQ_USER); dict.setDictionary(WnnDictionary.INDEX_LEARN_DICTIONARY, FREQ_LEARN, FREQ_LEARN); /* search dictionaries */ dict.searchWord(WnnDictionary.SEARCH_PREFIX, WnnDictionary.ORDER_BY_FREQUENCY, mSearchKey); return 1; } /** @see jp.co.omronsoft.openwnn.WnnEngine#convert */ public int convert(ComposingText text) { clearCandidates(); return 0; } /** @see jp.co.omronsoft.openwnn.WnnEngine#searchWords */ public int searchWords(String key) { clearCandidates(); return 0; } /** @see jp.co.omronsoft.openwnn.WnnEngine#searchWords */ public int searchWords(WnnWord word) { clearCandidates(); return 0; } /** @see jp.co.omronsoft.openwnn.WnnEngine#getNextCandidate */ public WnnWord getNextCandidate() { if (mSearchKey == null) { return null; } WnnWord word = getCandidate(mOutputNum); if (word != null) { mOutputNum++; } return word; } /** @see jp.co.omronsoft.openwnn.WnnEngine#learn */ public boolean learn(WnnWord word) { return ( mDictionary.learnWord(word) == 0 ); } /** @see jp.co.omronsoft.openwnn.WnnEngine#addWord */ public int addWord(WnnWord word) { WnnDictionary dict = mDictionary; dict.setInUseState( true ); dict.addWordToUserDictionary(word); dict.setInUseState( false ); return 0; } /** @see jp.co.omronsoft.openwnn.WnnEngine#deleteWord */ public boolean deleteWord(WnnWord word) { WnnDictionary dict = mDictionary; dict.setInUseState( true ); dict.removeWordFromUserDictionary(word); dict.setInUseState( false ); return false; } /** @see jp.co.omronsoft.openwnn.WnnEngine#setPreferences */ public void setPreferences(SharedPreferences pref) {} /** @see jp.co.omronsoft.openwnn.WnnEngine#breakSequence */ public void breakSequence() {} /** @see jp.co.omronsoft.openwnn.WnnEngine#makeCandidateListOf */ public int makeCandidateListOf(int clausePosition) {return 0;} /** @see jp.co.omronsoft.openwnn.WnnEngine#initializeDictionary */ public boolean initializeDictionary(int dictionary) { WnnDictionary dict = mDictionary; switch( dictionary ) { case WnnEngine.DICTIONARY_TYPE_LEARN: dict.setInUseState( true ); dict.clearLearnDictionary(); dict.setInUseState( false ); return true; case WnnEngine.DICTIONARY_TYPE_USER: dict.setInUseState( true ); dict.clearUserDictionary(); dict.setInUseState( false ); return true; } return false; } /** @see jp.co.omronsoft.openwnn.WnnEngine#initializeDictionary */ public boolean initializeDictionary(int dictionary, int type) { return initializeDictionary(dictionary); } /** @see jp.co.omronsoft.openwnn.WnnEngine#getUserDictionaryWords */ public WnnWord[] getUserDictionaryWords( ) { WnnDictionary dict = mDictionary; dict.setInUseState( true ); WnnWord[] result = dict.getUserDictionaryWords( ); dict.setInUseState( false ); return result; } }