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