Home | History | Annotate | Download | only in latin
      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.latin.SuggestedWords.SuggestedWordInfo;
     21 import com.android.inputmethod.latin.common.ComposedData;
     22 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
     23 
     24 import java.util.ArrayList;
     25 import java.util.Locale;
     26 import java.util.Arrays;
     27 import java.util.HashSet;
     28 
     29 /**
     30  * Abstract base class for a dictionary that can do a fuzzy search for words based on a set of key
     31  * strokes.
     32  */
     33 public abstract class Dictionary {
     34     public static final int NOT_A_PROBABILITY = -1;
     35     public static final float NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL = -1.0f;
     36 
     37     // The following types do not actually come from real dictionary instances, so we create
     38     // corresponding instances.
     39     public static final String TYPE_USER_TYPED = "user_typed";
     40     public static final PhonyDictionary DICTIONARY_USER_TYPED = new PhonyDictionary(TYPE_USER_TYPED);
     41 
     42     public static final String TYPE_USER_SHORTCUT = "user_shortcut";
     43     public static final PhonyDictionary DICTIONARY_USER_SHORTCUT =
     44             new PhonyDictionary(TYPE_USER_SHORTCUT);
     45 
     46     public static final String TYPE_APPLICATION_DEFINED = "application_defined";
     47     public static final PhonyDictionary DICTIONARY_APPLICATION_DEFINED =
     48             new PhonyDictionary(TYPE_APPLICATION_DEFINED);
     49 
     50     public static final String TYPE_HARDCODED = "hardcoded"; // punctuation signs and such
     51     public static final PhonyDictionary DICTIONARY_HARDCODED =
     52             new PhonyDictionary(TYPE_HARDCODED);
     53 
     54     // Spawned by resuming suggestions. Comes from a span that was in the TextView.
     55     public static final String TYPE_RESUMED = "resumed";
     56     public static final PhonyDictionary DICTIONARY_RESUMED = new PhonyDictionary(TYPE_RESUMED);
     57 
     58     // The following types of dictionary have actual functional instances. We don't need final
     59     // phony dictionary instances for them.
     60     public static final String TYPE_MAIN = "main";
     61     public static final String TYPE_CONTACTS = "contacts";
     62     // User dictionary, the system-managed one.
     63     public static final String TYPE_USER = "user";
     64     // User history dictionary internal to LatinIME.
     65     public static final String TYPE_USER_HISTORY = "history";
     66     public final String mDictType;
     67     // The locale for this dictionary. May be null if unknown (phony dictionary for example).
     68     public final Locale mLocale;
     69 
     70     /**
     71      * Set out of the dictionary types listed above that are based on data specific to the user,
     72      * e.g., the user's contacts.
     73      */
     74     private static final HashSet<String> sUserSpecificDictionaryTypes = new HashSet<>(Arrays.asList(
     75             TYPE_USER_TYPED,
     76             TYPE_USER,
     77             TYPE_CONTACTS,
     78             TYPE_USER_HISTORY));
     79 
     80     public Dictionary(final String dictType, final Locale locale) {
     81         mDictType = dictType;
     82         mLocale = locale;
     83     }
     84 
     85     /**
     86      * Searches for suggestions for a given context.
     87      * @param composedData the key sequence to match with coordinate info
     88      * @param ngramContext the context for n-gram.
     89      * @param proximityInfoHandle the handle for key proximity. Is ignored by some implementations.
     90      * @param settingsValuesForSuggestion the settings values used for the suggestion.
     91      * @param sessionId the session id.
     92      * @param weightForLocale the weight given to this locale, to multiply the output scores for
     93      * multilingual input.
     94      * @param inOutWeightOfLangModelVsSpatialModel the weight of the language model as a ratio of
     95      * the spatial model, used for generating suggestions. inOutWeightOfLangModelVsSpatialModel is
     96      * a float array that has only one element. This can be updated when a different value is used.
     97      * @return the list of suggestions (possibly null if none)
     98      */
     99     abstract public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedData,
    100             final NgramContext ngramContext, final long proximityInfoHandle,
    101             final SettingsValuesForSuggestion settingsValuesForSuggestion,
    102             final int sessionId, final float weightForLocale,
    103             final float[] inOutWeightOfLangModelVsSpatialModel);
    104 
    105     /**
    106      * Checks if the given word has to be treated as a valid word. Please note that some
    107      * dictionaries have entries that should be treated as invalid words.
    108      * @param word the word to search for. The search should be case-insensitive.
    109      * @return true if the word is valid, false otherwise
    110      */
    111     public boolean isValidWord(final String word) {
    112         return isInDictionary(word);
    113     }
    114 
    115     /**
    116      * Checks if the given word is in the dictionary regardless of it being valid or not.
    117      */
    118     abstract public boolean isInDictionary(final String word);
    119 
    120     /**
    121      * Get the frequency of the word.
    122      * @param word the word to get the frequency of.
    123      */
    124     public int getFrequency(final String word) {
    125         return NOT_A_PROBABILITY;
    126     }
    127 
    128     /**
    129      * Get the maximum frequency of the word.
    130      * @param word the word to get the maximum frequency of.
    131      */
    132     public int getMaxFrequencyOfExactMatches(final String word) {
    133         return NOT_A_PROBABILITY;
    134     }
    135 
    136     /**
    137      * Compares the contents of the character array with the typed word and returns true if they
    138      * are the same.
    139      * @param word the array of characters that make up the word
    140      * @param length the number of valid characters in the character array
    141      * @param typedWord the word to compare with
    142      * @return true if they are the same, false otherwise.
    143      */
    144     protected boolean same(final char[] word, final int length, final String typedWord) {
    145         if (typedWord.length() != length) {
    146             return false;
    147         }
    148         for (int i = 0; i < length; i++) {
    149             if (word[i] != typedWord.charAt(i)) {
    150                 return false;
    151             }
    152         }
    153         return true;
    154     }
    155 
    156     /**
    157      * Override to clean up any resources.
    158      */
    159     public void close() {
    160         // empty base implementation
    161     }
    162 
    163     /**
    164      * Subclasses may override to indicate that this Dictionary is not yet properly initialized.
    165      */
    166     public boolean isInitialized() {
    167         return true;
    168     }
    169 
    170     /**
    171      * Whether we think this suggestion should trigger an auto-commit. prevWord is the word
    172      * before the suggestion, so that we can use n-gram frequencies.
    173      * @param candidate The candidate suggestion, in whole (not only the first part).
    174      * @return whether we should auto-commit or not.
    175      */
    176     public boolean shouldAutoCommit(final SuggestedWordInfo candidate) {
    177         // If we don't have support for auto-commit, or if we don't know, we return false to
    178         // avoid auto-committing stuff. Implementations of the Dictionary class that know to
    179         // determine whether we should auto-commit will override this.
    180         return false;
    181     }
    182 
    183     /**
    184      * Whether this dictionary is based on data specific to the user, e.g., the user's contacts.
    185      * @return Whether this dictionary is specific to the user.
    186      */
    187     public boolean isUserSpecific() {
    188         return sUserSpecificDictionaryTypes.contains(mDictType);
    189     }
    190 
    191     /**
    192      * Not a true dictionary. A placeholder used to indicate suggestions that don't come from any
    193      * real dictionary.
    194      */
    195     @UsedForTesting
    196     static class PhonyDictionary extends Dictionary {
    197         @UsedForTesting
    198         PhonyDictionary(final String type) {
    199             super(type, null);
    200         }
    201 
    202         @Override
    203         public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedData,
    204                 final NgramContext ngramContext, final long proximityInfoHandle,
    205                 final SettingsValuesForSuggestion settingsValuesForSuggestion,
    206                 final int sessionId, final float weightForLocale,
    207                 final float[] inOutWeightOfLangModelVsSpatialModel) {
    208             return null;
    209         }
    210 
    211         @Override
    212         public boolean isInDictionary(String word) {
    213             return false;
    214         }
    215     }
    216 }
    217