1 /*
2  * Copyright (C) 2008 The Android Open Source Project
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 
17 package com.android.inputmethod.latin;
18 
19 import com.android.inputmethod.annotations.UsedForTesting;
20 import com.android.inputmethod.keyboard.ProximityInfo;
21 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
22 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
23 
24 import java.util.ArrayList;
25 
26 /**
27  * Abstract base class for a dictionary that can do a fuzzy search for words based on a set of key
28  * strokes.
29  */
30 public abstract class Dictionary {
31     public static final int NOT_A_PROBABILITY = -1;
32     public static final float NOT_A_LANGUAGE_WEIGHT = -1.0f;
33 
34     // The following types do not actually come from real dictionary instances, so we create
35     // corresponding instances.
36     public static final String TYPE_USER_TYPED = "user_typed";
37     public static final Dictionary DICTIONARY_USER_TYPED = new PhonyDictionary(TYPE_USER_TYPED);
38 
39     public static final String TYPE_APPLICATION_DEFINED = "application_defined";
40     public static final Dictionary DICTIONARY_APPLICATION_DEFINED =
41             new PhonyDictionary(TYPE_APPLICATION_DEFINED);
42 
43     public static final String TYPE_HARDCODED = "hardcoded"; // punctuation signs and such
44     public static final Dictionary DICTIONARY_HARDCODED =
45             new PhonyDictionary(TYPE_HARDCODED);
46 
47     // Spawned by resuming suggestions. Comes from a span that was in the TextView.
48     public static final String TYPE_RESUMED = "resumed";
49     public static final Dictionary DICTIONARY_RESUMED =
50             new PhonyDictionary(TYPE_RESUMED);
51 
52     // The following types of dictionary have actual functional instances. We don't need final
53     // phony dictionary instances for them.
54     public static final String TYPE_MAIN = "main";
55     public static final String TYPE_CONTACTS = "contacts";
56     // User dictionary, the system-managed one.
57     public static final String TYPE_USER = "user";
58     // User history dictionary internal to LatinIME.
59     public static final String TYPE_USER_HISTORY = "history";
60     // Personalization dictionary.
61     public static final String TYPE_PERSONALIZATION = "personalization";
62     // Contextual dictionary.
63     public static final String TYPE_CONTEXTUAL = "contextual";
64     public final String mDictType;
65 
Dictionary(final String dictType)66     public Dictionary(final String dictType) {
67         mDictType = dictType;
68     }
69 
70     /**
71      * Searches for suggestions for a given context. For the moment the context is only the
72      * previous word.
73      * @param composer the key sequence to match with coordinate info, as a WordComposer
74      * @param prevWordsInfo the information of previous words.
75      * @param proximityInfo the object for key proximity. May be ignored by some implementations.
76      * @param settingsValuesForSuggestion the settings values used for the suggestion.
77      * @param sessionId the session id.
78      * @param inOutLanguageWeight the language weight used for generating suggestions.
79      * inOutLanguageWeight is a float array that has only one element. This can be updated when the
80      * different language weight is used.
81      * @return the list of suggestions (possibly null if none)
82      */
getSuggestions(final WordComposer composer, final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId, final float[] inOutLanguageWeight)83     abstract public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
84             final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
85             final SettingsValuesForSuggestion settingsValuesForSuggestion,
86             final int sessionId, final float[] inOutLanguageWeight);
87 
88     /**
89      * Checks if the given word has to be treated as a valid word. Please note that some
90      * dictionaries have entries that should be treated as invalid words.
91      * @param word the word to search for. The search should be case-insensitive.
92      * @return true if the word is valid, false otherwise
93      */
isValidWord(final String word)94     public boolean isValidWord(final String word) {
95         return isInDictionary(word);
96     }
97 
98     /**
99      * Checks if the given word is in the dictionary regardless of it being valid or not.
100      */
isInDictionary(final String word)101     abstract public boolean isInDictionary(final String word);
102 
getFrequency(final String word)103     public int getFrequency(final String word) {
104         return NOT_A_PROBABILITY;
105     }
106 
getMaxFrequencyOfExactMatches(final String word)107     public int getMaxFrequencyOfExactMatches(final String word) {
108         return NOT_A_PROBABILITY;
109     }
110 
111     /**
112      * Compares the contents of the character array with the typed word and returns true if they
113      * are the same.
114      * @param word the array of characters that make up the word
115      * @param length the number of valid characters in the character array
116      * @param typedWord the word to compare with
117      * @return true if they are the same, false otherwise.
118      */
same(final char[] word, final int length, final String typedWord)119     protected boolean same(final char[] word, final int length, final String typedWord) {
120         if (typedWord.length() != length) {
121             return false;
122         }
123         for (int i = 0; i < length; i++) {
124             if (word[i] != typedWord.charAt(i)) {
125                 return false;
126             }
127         }
128         return true;
129     }
130 
131     /**
132      * Override to clean up any resources.
133      */
close()134     public void close() {
135         // empty base implementation
136     }
137 
138     /**
139      * Subclasses may override to indicate that this Dictionary is not yet properly initialized.
140      */
isInitialized()141     public boolean isInitialized() {
142         return true;
143     }
144 
145     /**
146      * Whether we think this suggestion should trigger an auto-commit. prevWord is the word
147      * before the suggestion, so that we can use n-gram frequencies.
148      * @param candidate The candidate suggestion, in whole (not only the first part).
149      * @return whether we should auto-commit or not.
150      */
shouldAutoCommit(final SuggestedWordInfo candidate)151     public boolean shouldAutoCommit(final SuggestedWordInfo candidate) {
152         // If we don't have support for auto-commit, or if we don't know, we return false to
153         // avoid auto-committing stuff. Implementations of the Dictionary class that know to
154         // determine whether we should auto-commit will override this.
155         return false;
156     }
157 
158     /**
159      * Not a true dictionary. A placeholder used to indicate suggestions that don't come from any
160      * real dictionary.
161      */
162     private static class PhonyDictionary extends Dictionary {
163         // This class is not publicly instantiable.
PhonyDictionary(final String type)164         private PhonyDictionary(final String type) {
165             super(type);
166         }
167 
168         @Override
getSuggestions(final WordComposer composer, final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId, final float[] inOutLanguageWeight)169         public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
170                 final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
171                 final SettingsValuesForSuggestion settingsValuesForSuggestion,
172                 final int sessionId, final float[] inOutLanguageWeight) {
173             return null;
174         }
175 
176         @Override
isInDictionary(String word)177         public boolean isInDictionary(String word) {
178             return false;
179         }
180     }
181 }
182