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