1053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project/*
259aefa242169b7a51c2381daee58ff22fd1834ceJunichi Monma * Copyright (C) 2008-2012  OMRON SOFTWARE Co., Ltd.
3053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project *
4053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project * you may not use this file except in compliance with the License.
6053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project * You may obtain a copy of the License at
7053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project *
8053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project *
10053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project * See the License for the specific language governing permissions and
14053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project * limitations under the License.
15053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project */
16053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
17053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Projectpackage jp.co.omronsoft.openwnn.JAJP;
18053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
19053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Projectimport jp.co.omronsoft.openwnn.*;
20053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Projectimport java.util.*;
21053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
22053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project/**
233feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa * The penWnn Clause Converter class for Japanese IME.
24053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project *
253feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa * @author Copyright (C) 2009 OMRON SOFTWARE CO., LTD.  All Rights Reserved.
26053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project */
27053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Projectpublic class OpenWnnClauseConverterJAJP {
28053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /** Score(frequency value) of word in the learning dictionary */
29053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private static final int FREQ_LEARN = 600;
30053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /** Score(frequency value) of word in the user dictionary */
31053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private static final int FREQ_USER  = 500;
32053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
33053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /** Maximum limit length of input */
34053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    public static final int MAX_INPUT_LENGTH = 50;
35053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
367b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa    /** search cache for unique independent words (jiritsugo) */
377b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa    private HashMap<String, ArrayList<WnnWord>> mIndepWordBag;
387b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa    /** search cache for all independent words (jiritsugo) */
397b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa    private HashMap<String, ArrayList<WnnWord>> mAllIndepWordBag;
40053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /** search cache for ancillary words (fuzokugo) */
417b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa    private HashMap<String, ArrayList<WnnWord>> mFzkPatterns;
42053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
43053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /** connect matrix for generating a clause */
44053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private byte[][] mConnectMatrix;
45053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
46053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /** dictionaries */
47053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private WnnDictionary mDictionary;
48053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
49053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /** candidates of conversion */
50053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private LinkedList mConvertResult;
51053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
52053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /** work area for consecutive clause conversion */
53053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private WnnSentence[] mSentenceBuffer;
54053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
55053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /** part of speech (default) */
56053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private WnnPOS mPosDefault;
57053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /** part of speech (end of clause/not end of sentence) */
58053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private WnnPOS mPosEndOfClause1;
59053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /** part of speech (end of clause/any place) */
60053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private WnnPOS mPosEndOfClause2;
61053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /** part of speech (end of sentence) */
62053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private WnnPOS mPosEndOfClause3;
63053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
64053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /** cost value of a clause */
65053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private static final int CLAUSE_COST = -1000;
667b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa
677b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa    /** The candidate filter */
687b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa    private CandidateFilter mFilter = null;
69053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
70053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /**
71053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * Constructor
72053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     */
73053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    public OpenWnnClauseConverterJAJP() {
747b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa        mIndepWordBag  = new HashMap<String, ArrayList<WnnWord>>();
757b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa        mAllIndepWordBag  = new HashMap<String, ArrayList<WnnWord>>();
76053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        mFzkPatterns   = new HashMap();
77053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        mConvertResult = new LinkedList();
78053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
79053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        mSentenceBuffer = new WnnSentence[MAX_INPUT_LENGTH];
80053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    }
81053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
82053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /**
83053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * Set the dictionary
84053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     *
85053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * @param dict  The dictionary for phrase conversion
86053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     */
87053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    public void setDictionary(WnnDictionary dict) {
88053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* get connect matrix */
89053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        mConnectMatrix = dict.getConnectMatrix();
90053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
91053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* clear dictionary settings */
92053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        mDictionary = dict;
93053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        dict.clearDictionary();
94053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        dict.clearApproxPattern();
95053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
96053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* clear work areas */
97053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        mIndepWordBag.clear();
987b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa        mAllIndepWordBag.clear();
99053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        mFzkPatterns.clear();
1007b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa
101053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* get part of speech tags */
102053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        mPosDefault      = dict.getPOS(WnnDictionary.POS_TYPE_MEISI);
103053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        mPosEndOfClause1 = dict.getPOS(WnnDictionary.POS_TYPE_V1);
104053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        mPosEndOfClause2 = dict.getPOS(WnnDictionary.POS_TYPE_V2);
105053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        mPosEndOfClause3 = dict.getPOS(WnnDictionary.POS_TYPE_V3);
106053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    }
1077b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa
1087b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa    /**
1097b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa     * Set the candidate filter
1103feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     *
1113feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param filter	The candidate filter
1127b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa     */
1137b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa    public void setFilter(CandidateFilter filter) {
1147b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa    	mFilter = filter;
1157b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa    }
116053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
117053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /**
118053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * Kana-to-Kanji conversion (single clause).
119053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * <br>
120053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * This method execute single clause conversion.
121053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project      *
1223feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param input		The input string
1233feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @return			The candidates of conversion; {@code null} if an error occurs.
124053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     */
125053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     public Iterator convert(String input) {
126053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* do nothing if no dictionary is specified */
127053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        if (mConnectMatrix == null || mDictionary == null) {
128053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            return null;
129053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
130053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* do nothing if the length of input exceeds the limit */
131053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        if (input.length() > MAX_INPUT_LENGTH) {
132053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            return null;
133053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
134053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
135053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* clear the candidates list */
136053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        mConvertResult.clear();
137053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
138053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* try single clause conversion */
139053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        if (!singleClauseConvert(mConvertResult, input, mPosEndOfClause2, true)) {
140053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            return null;
141053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
142053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        return mConvertResult.iterator();
143053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    }
144053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
145053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /**
146053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * Consecutive clause conversion.
147053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     *
1483feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param input		The input string
1493feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @return			The result of consecutive clause conversion; {@code null} if fail.
150053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     */
151053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    public WnnSentence consecutiveClauseConvert(String input) {
152053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        LinkedList clauses = new LinkedList();
153053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
154053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* clear the cache which is not matched */
1557b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa        for (int i = 0; i < input.length(); i++) {
156053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            mSentenceBuffer[i] = null;
157053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
158053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        WnnSentence[] sentence = mSentenceBuffer;
159053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
160053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* consecutive clause conversion */
161053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        for (int start = 0; start < input.length(); start++) {
162053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            if (start != 0 && sentence[start-1] == null) {
163053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                continue;
164053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
165053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
166053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            /* limit the length of a clause */
167053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            int end = input.length();
168053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            if (end > start + 20) {
169053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                end = start + 20;
170053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
171053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            /* make clauses */
1727b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa            for ( ; end > start; end--) {
173053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                int idx = end - 1;
174053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
175053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                /* cutting a branch */
176053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                if (sentence[idx] != null) {
177053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    if (start != 0) {
178053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        if (sentence[idx].frequency > sentence[start-1].frequency + CLAUSE_COST + FREQ_LEARN) {
179053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                            /* there may be no way to be the best sequence from the 'start' */
180053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                            break;
181053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        }
182053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    } else {
183053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        if (sentence[idx].frequency > CLAUSE_COST + FREQ_LEARN) {
184053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                            /* there may be no way to be the best sequence from the 'start' */
185053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                            break;
186053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        }
187053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    }
188053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                }
189053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
190053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                String key = input.substring(start, end);
191053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                clauses.clear();
192053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                WnnClause bestClause = null;
193053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                if (end == input.length()) {
194053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    /* get the clause which can be the end of the sentence */
195053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    singleClauseConvert(clauses, key, mPosEndOfClause1, false);
196053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                } else {
197053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    /* get the clause which is not the end of the sentence */
198053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    singleClauseConvert(clauses, key, mPosEndOfClause3, false);
199053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                }
200053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                if (clauses.isEmpty()) {
201053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    bestClause = defaultClause(key);
202053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                } else {
203053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    bestClause = (WnnClause)clauses.get(0);
204053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                }
205053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
206053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                /* make a sub-sentence */
207053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                WnnSentence ws;
208053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                if (start == 0) {
209053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    ws = new WnnSentence(key, bestClause);
210053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                } else {
211053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    ws = new WnnSentence(sentence[start-1], bestClause);
212053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                }
213053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                ws.frequency += CLAUSE_COST;
214053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
215053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                /* update the best sub-sentence on the cache buffer */
216053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                if (sentence[idx] == null || (sentence[idx].frequency < ws.frequency)) {
217053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    sentence[idx] = ws;
218053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                }
219053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
220053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
221053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
222053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* return the result of the consecutive clause conversion */
223053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        if (sentence[input.length() - 1] != null) {
224053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            return sentence[input.length() - 1];
225053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
226053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        return null;
227053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    }
228053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
229053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /**
230053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * Consecutive clause conversion.
231053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     *
2323feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param resultList	Where to store the result
2333feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param input			Input string
2343feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @return				{@code true} if success; {@code false} if fail.
235053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     */
236053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private boolean consecutiveClauseConvert(LinkedList resultList, String input) {
237053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        WnnSentence sentence = consecutiveClauseConvert(input);
238053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
239053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* set the result of the consecutive clause conversion on the top of the list */
240053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        if (sentence != null) {
241053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            resultList.add(0, sentence);
242053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            return true;
243053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
244053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        return false;
245053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    }
246053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
247053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /**
248053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * Single clause conversion.
249053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     *
2503feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param clauseList	Where to store the results
2513feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param input			Input string
2523feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param terminal		Part of speech tag at the terminal
2533feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param all			Get all candidates or not
2543feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @return				{@code true} if success; {@code false} if fail.
255053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     */
256053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private boolean singleClauseConvert(LinkedList clauseList, String input, WnnPOS terminal, boolean all) {
257053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        boolean ret = false;
258053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
259053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* get clauses without ancillary word */
2607b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa        ArrayList<WnnWord> stems = getIndependentWords(input, all);
261053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        if (stems != null && (!stems.isEmpty())) {
2627b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa            Iterator<WnnWord> stemsi = stems.iterator();
263053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            while (stemsi.hasNext()) {
2647b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa                WnnWord stem = stemsi.next();
265053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                if (addClause(clauseList, input, stem, null, terminal, all)) {
266053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    ret = true;
267053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                }
268053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
269053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
270053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
271053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* get clauses with ancillary word */
272053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        int max = CLAUSE_COST * 2;
273053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        for (int split = 1; split < input.length(); split++) {
274053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            /* get ancillary patterns */
275053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            String str = input.substring(split);
2767b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa            ArrayList<WnnWord> fzks = getAncillaryPattern(str);
277053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            if (fzks == null || fzks.isEmpty()) {
278053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                continue;
279053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
280053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
281053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            /* get candidates of stem in a clause */
282053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            str = input.substring(0, split);
283053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            stems = getIndependentWords(str, all);
284053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            if (stems == null || stems.isEmpty()) {
285053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                if (mDictionary.searchWord(WnnDictionary.SEARCH_PREFIX, WnnDictionary.ORDER_BY_FREQUENCY, str) <= 0) {
286053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    break;
287053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                } else {
288053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    continue;
289053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                }
290053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
291053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            /* make clauses */
2927b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa            Iterator<WnnWord> stemsi = stems.iterator();
293053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            while (stemsi.hasNext()) {
2947b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa                WnnWord stem = stemsi.next();
295053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                if (all || stem.frequency > max) {
2967b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa                    Iterator<WnnWord> fzksi  = fzks.iterator();
297053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    while (fzksi.hasNext()) {
2987b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa                        WnnWord fzk = fzksi.next();
299053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        if (addClause(clauseList, input, stem, fzk, terminal, all)) {
300053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                            ret = true;
301053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                            max = stem.frequency;
302053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        }
303053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    }
304053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                }
305053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
306053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
307053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        return ret;
308053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    }
309053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
310053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /**
311053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * Add valid clause to the candidates list.
312053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     *
3133feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param clauseList	Where to store the results
3143feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param input			Input string
3153feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param stem			Stem of the clause (a independent word)
3163feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param fzk			Ancillary pattern
3173feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param terminal		Part of speech tag at the terminal
3183feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param all			Get all candidates or not
3193feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @return				{@code true} if add the clause to the list; {@code false} if not.
320053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     */
321053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private boolean addClause(LinkedList<WnnClause> clauseList, String input, WnnWord stem, WnnWord fzk,
322053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                              WnnPOS terminal, boolean all) {
323053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        WnnClause clause = null;
324053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* check if the part of speech is valid */
325053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        if (fzk == null) {
326053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            if (connectible(stem.partOfSpeech.right, terminal.left)) {
327053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                clause = new WnnClause(input, stem);
328053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
329053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        } else {
330053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            if (connectible(stem.partOfSpeech.right, fzk.partOfSpeech.left)
331053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                && connectible(fzk.partOfSpeech.right, terminal.left)) {
332053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                clause = new WnnClause(input, stem, fzk);
333053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
334053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
335053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        if (clause == null) {
336053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            return false;
337053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
3387b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa        if (mFilter != null && !mFilter.isAllowed(clause)) {
3397b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa        	return false;
3407b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa        }
341053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
342053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* store to the list */
343053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        if (clauseList.isEmpty()) {
344053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            /* add if the list is empty */
345053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            clauseList.add(0, clause);
346053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            return true;
347053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        } else {
348053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            if (!all) {
349053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                /* reserve only the best clause */
350053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                WnnClause best = (WnnClause)clauseList.get(0);
351053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                if (best.frequency < clause.frequency) {
352053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    clauseList.set(0, clause);
353053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    return true;
354053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                }
355053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            } else {
356053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                /* reserve all clauses */
357053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                Iterator clauseListi = clauseList.iterator();
358053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                int index = 0;
359053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                while (clauseListi.hasNext()) {
360053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    WnnClause clausei = (WnnClause)clauseListi.next();
361053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    if (clausei.frequency < clause.frequency) {
362053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        break;
363053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    }
364053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    index++;
365053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                }
366053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                clauseList.add(index, clause);
367053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                return true;
368053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
369053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
370053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
371053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        return false;
372053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    }
373053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
374053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /**
3753feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * Check the part-of-speeches are connectable.
376053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     *
3773feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param right		Right attribute of the preceding word/clause
3783feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param left		Left attribute of the following word/clause
3793feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @return			{@code true} if there are connectable; {@code false} if otherwise
380053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     */
381053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private boolean connectible(int right, int left) {
382053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        try {
383053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            if (mConnectMatrix[left][right] != 0) {
384053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                return true;
385053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
386053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        } catch (Exception ex) {
387053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
388053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        return false;
389053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    }
390053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
391053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /**
392053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * Get all exact matched ancillary words(Fuzokugo) list.
393053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     *
3943feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param input		Search key
3953feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @return			List of ancillary words
396053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     */
3977b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa    private ArrayList<WnnWord> getAncillaryPattern(String input) {
398053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        if (input.length() == 0) {
399053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            return null;
400053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
401053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
4027b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa        HashMap<String,ArrayList<WnnWord>> fzkPat = mFzkPatterns;
4037b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa        ArrayList<WnnWord> fzks = fzkPat.get(input);
404053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        if (fzks != null) {
405053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            return fzks;
406053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
407053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
408053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        /* set dictionaries */
409053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        WnnDictionary dict = mDictionary;
410053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        dict.clearDictionary();
411053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        dict.clearApproxPattern();
412053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        dict.setDictionary(6, 400, 500);
413053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
414053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        for (int start = input.length() - 1; start >= 0; start--) {
415053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            String key = input.substring(start);
416053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
417053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            fzks = fzkPat.get(key);
418053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            if (fzks != null) {
419053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                continue;
420053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
421053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
4227b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa            fzks = new ArrayList<WnnWord>();
423053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            mFzkPatterns.put(key, fzks);
424053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
425053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            /* search ancillary words */
426053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            dict.searchWord(WnnDictionary.SEARCH_EXACT, WnnDictionary.ORDER_BY_FREQUENCY, key);
427053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            WnnWord word;
428053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            while ((word = dict.getNextWord()) != null) {
429053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                fzks.add(word);
430053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
431053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
432053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            /* concatenate sequence of ancillary words */
433053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            for (int end = input.length() - 1; end > start; end--) {
4347b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa                ArrayList<WnnWord> followFzks = fzkPat.get(input.substring(end));
435053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                if (followFzks == null ||  followFzks.isEmpty()) {
436053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    continue;
437053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                }
438053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                dict.searchWord(WnnDictionary.SEARCH_EXACT, WnnDictionary.ORDER_BY_FREQUENCY, input.substring(start, end));
439053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                while ((word = dict.getNextWord()) != null) {
4407b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa                    Iterator<WnnWord> followFzksi = followFzks.iterator();
441053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    while (followFzksi.hasNext()) {
4427b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa                        WnnWord follow = followFzksi.next();
443053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        if (connectible(word.partOfSpeech.right, follow.partOfSpeech.left)) {
444053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                            fzks.add(new WnnWord(key, key, new WnnPOS(word.partOfSpeech.left, follow.partOfSpeech.right)));
445053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        }
446053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    }
447053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                }
448053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
449053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
450053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        return fzks;
451053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    }
452053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
453053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /**
454053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * Get all exact matched independent words(Jiritsugo) list.
455053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     *
4563feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param input    Search key
4573feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param all      {@code true} if list all words; {@code false} if list words which has an unique part of speech tag.
4583feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @return			List of words; {@code null} if {@code input.length() == 0}.
459053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     */
4607b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa    private ArrayList<WnnWord> getIndependentWords(String input, boolean all) {
461053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        if (input.length() == 0) {
462053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            return null;
463053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
464053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
4657b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa        ArrayList<WnnWord> words = (all)? mAllIndepWordBag.get(input) : mIndepWordBag.get(input);
466053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
467053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        if (words == null) {
468053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            /* set dictionaries */
469053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            WnnDictionary dict = mDictionary;
470053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            dict.clearDictionary();
471053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            dict.clearApproxPattern();
472053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            dict.setDictionary(4, 0, 10);
473053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            dict.setDictionary(5, 400, 500);
474053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            dict.setDictionary(WnnDictionary.INDEX_USER_DICTIONARY, FREQ_USER, FREQ_USER);
475053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            dict.setDictionary(WnnDictionary.INDEX_LEARN_DICTIONARY, FREQ_LEARN, FREQ_LEARN);
476053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
4777b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa            words = new ArrayList<WnnWord>();
478053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            WnnWord word;
479053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            if (all) {
4807b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa            	mAllIndepWordBag.put(input, words);
4817b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa                dict.searchWord(WnnDictionary.SEARCH_EXACT, WnnDictionary.ORDER_BY_FREQUENCY, input);
482053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                /* store all words */
483053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                while ((word = dict.getNextWord()) != null) {
484053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    if (input.equals(word.stroke)) {
485053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        words.add(word);
486053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    }
487053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                }
488053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            } else {
4897b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa            	mIndepWordBag.put(input, words);
4907b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa                dict.searchWord(WnnDictionary.SEARCH_EXACT, WnnDictionary.ORDER_BY_FREQUENCY, input);
491053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                /* store a word which has an unique part of speech tag */
492053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                while ((word = dict.getNextWord()) != null) {
493053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    if (input.equals(word.stroke)) {
4947b3b414976b6b3d6d85459de79e843d5ab35ed06Daisuke Miyakawa                        Iterator<WnnWord> list = words.iterator();
495053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        boolean found = false;
496053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        while (list.hasNext()) {
497053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                            WnnWord w = (WnnWord)list.next();
498053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                                if (w.partOfSpeech.right == word.partOfSpeech.right) {
499053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                                    found = true;
500053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                                    break;
501053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                                }
502053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        }
503053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        if (!found) {
504053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                            words.add(word);
505053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        }
506053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        if (word.frequency < 400) {
507053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                            break;
508053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                        }
509053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                    }
510053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project                }
511053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            }
512053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project            addAutoGeneratedCandidates(input, words, all);
513053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        }
514053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        return words;
515053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    }
516053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
517053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /**
518053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * Add some words not including in the dictionary.
519053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * <br>
520053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * This method adds some words which are not in the dictionary.
521053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     *
5223feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param input     Input string
5233feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param wordList  List to store words
5243feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param all       Get all candidates or not
525053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     */
526053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private void addAutoGeneratedCandidates(String input, ArrayList wordList, boolean all) {
527053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        wordList.add(new WnnWord(input, input, mPosDefault, (CLAUSE_COST - 1) * input.length()));
528053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    }
529053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project
530053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    /**
531053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * Get a default clause.
532053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * <br>
533053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * This method generates a clause which has a string same as input
534053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     * and the default part-of-speech tag.
535053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     *
5363feb3d26d59be1626c59b72654020179e2b2ebe0Daisuke Miyakawa     * @param input    Input string
537e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa     * @return			Default clause
538053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project     */
539053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    private WnnClause defaultClause(String input) {
540053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project        return (new WnnClause(input, input, mPosDefault, (CLAUSE_COST - 1) * input.length()));
541053d50935e0e311286543bd7c535ae2c863c0deThe Android Open Source Project    }
54259aefa242169b7a51c2381daee58ff22fd1834ceJunichi Monma}