3939import java .util .concurrent .locks .ReentrantReadWriteLock ;
4040
4141/**
42- * Abstract base class for an expandable dictionary that can be created and updated dynamically
43- * during runtime. When updated it automatically generates a new binary dictionary to handle future
44- * queries in native code. This binary dictionary is written to internal storage.
42+ * Abstract base class for an expandable dictionary that can be created and
43+ * updated dynamically
44+ * during runtime. When updated it automatically generates a new binary
45+ * dictionary to handle future
46+ * queries in native code. This binary dictionary is written to internal
47+ * storage.
4548 * <p>
46- * A class that extends this abstract class must have a static factory method named
47- * getDictionary(Context context, Locale locale, File dictFile, String dictNamePrefix)
49+ * A class that extends this abstract class must have a static factory method
50+ * named
51+ * getDictionary(Context context, Locale locale, File dictFile, String
52+ * dictNamePrefix)
4853 */
4954abstract public class ExpandableBinaryDictionary extends Dictionary {
5055 private static final boolean DEBUG = false ;
@@ -60,25 +65,25 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
6065 /**
6166 * The maximum length of a word in this dictionary.
6267 */
63- protected static final int MAX_WORD_LENGTH =
64- DecoderSpecificConstants .DICTIONARY_MAX_WORD_LENGTH ;
68+ protected static final int MAX_WORD_LENGTH = DecoderSpecificConstants .DICTIONARY_MAX_WORD_LENGTH ;
6569
6670 private static final int DICTIONARY_FORMAT_VERSION = FormatSpec .VERSION4 ;
6771
68- private static final WordProperty [] DEFAULT_WORD_PROPERTIES_FOR_SYNC =
69- new WordProperty [0 ] /* default */ ;
72+ private static final WordProperty [] DEFAULT_WORD_PROPERTIES_FOR_SYNC = new WordProperty [0 ] /* default */ ;
7073
7174 /** The application context. */
7275 public final Context mContext ;
7376
7477 /**
75- * The binary dictionary generated dynamically from the fusion dictionary. This is used to
78+ * The binary dictionary generated dynamically from the fusion dictionary. This
79+ * is used to
7680 * answer unigram and bigram queries.
7781 */
7882 private BinaryDictionary mBinaryDictionary ;
7983
8084 /**
81- * The name of this dictionary, used as a part of the filename for storing the binary
85+ * The name of this dictionary, used as a part of the filename for storing the
86+ * binary
8287 * dictionary.
8388 */
8489 private final String mDictName ;
@@ -107,8 +112,10 @@ static boolean matchesExpectedBinaryDictFormatVersionForThisType(final int forma
107112 }
108113
109114 private static boolean needsToMigrateDictionary (final int formatVersion ) {
110- // When we bump up the dictionary format version, the old version should be added to here
111- // for supporting migration. Note that native code has to support reading such formats.
115+ // When we bump up the dictionary format version, the old version should be
116+ // added to here
117+ // for supporting migration. Note that native code has to support reading such
118+ // formats.
112119 return formatVersion == FormatSpec .VERSION402 ;
113120 }
114121
@@ -119,13 +126,14 @@ public boolean isValidDictionaryLocked() {
119126 /**
120127 * Creates a new expandable binary dictionary.
121128 *
122- * @param context The application context of the parent.
129+ * @param context The application context of the parent.
123130 * @param dictName The name of the dictionary. Multiple instances with the same
124- * name is supported.
125- * @param locale the dictionary locale.
131+ * name is supported.
132+ * @param locale the dictionary locale.
126133 * @param dictType the dictionary type, as a human-readable string
127- * @param dictFile dictionary file path. if null, use default dictionary path based on
128- * dictionary type.
134+ * @param dictFile dictionary file path. if null, use default dictionary path
135+ * based on
136+ * dictionary type.
129137 */
130138 public ExpandableBinaryDictionary (final Context context , final String dictName ,
131139 final Locale locale , final String dictType , final File dictFile ) {
@@ -174,6 +182,9 @@ BinaryDictionary getBinaryDictionary() {
174182 public int getFrequency (final String word ) {
175183 if (mLock .readLock ().tryLock ()) {
176184 try {
185+ if (mBinaryDictionary == null ) {
186+ return NOT_A_PROBABILITY ;
187+ }
177188 return mBinaryDictionary .getFrequency (word );
178189 } finally {
179190 mLock .readLock ().unlock ();
@@ -266,7 +277,8 @@ private void updateDictionaryWithWriteLock(@NonNull final Runnable updateTask) {
266277 }
267278
268279 /**
269- * Adds unigram information of a word to the dictionary. May overwrite an existing entry.
280+ * Adds unigram information of a word to the dictionary. May overwrite an
281+ * existing entry.
270282 */
271283 public void addUnigramEntry (final String word , final int frequency ,
272284 final String shortcutTarget , final int shortcutFreq , final boolean isNotAWord ,
@@ -304,7 +316,8 @@ public void removeUnigramEntryDynamically(final String word) {
304316 }
305317
306318 /**
307- * Adds n-gram information of a word to the dictionary. May overwrite an existing entry.
319+ * Adds n-gram information of a word to the dictionary. May overwrite an
320+ * existing entry.
308321 */
309322 public void addNgramEntry (@ NonNull final NgramContext ngramContext , final String word ,
310323 final int frequency , final int timestamp ) {
@@ -362,12 +375,12 @@ public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedDa
362375 if (mBinaryDictionary == null ) {
363376 return null ;
364377 }
365- final ArrayList <SuggestedWordInfo > suggestions =
366- mBinaryDictionary . getSuggestions ( composedData , ngramContext ,
367- proximityInfoHandle , settingsValuesForSuggestion , sessionId ,
368- weightForLocale , inOutWeightOfLangModelVsSpatialModel );
378+ final ArrayList <SuggestedWordInfo > suggestions = mBinaryDictionary . getSuggestions ( composedData ,
379+ ngramContext ,
380+ proximityInfoHandle , settingsValuesForSuggestion , sessionId ,
381+ weightForLocale , inOutWeightOfLangModelVsSpatialModel );
369382 if (mBinaryDictionary .isCorrupted ()) {
370- Log .i (TAG , "Dictionary (" + mDictName +") is corrupted. "
383+ Log .i (TAG , "Dictionary (" + mDictName + ") is corrupted. "
371384 + "Remove and regenerate it." );
372385 removeBinaryDictionary ();
373386 }
@@ -407,7 +420,8 @@ public boolean isInDictionary(final String word) {
407420 }
408421
409422 protected boolean isInDictionaryLocked (final String word ) {
410- if (mBinaryDictionary == null ) return false ;
423+ if (mBinaryDictionary == null )
424+ return false ;
411425 return mBinaryDictionary .isInDictionary (word );
412426 }
413427
@@ -434,14 +448,15 @@ public int getMaxFrequencyOfExactMatches(final String word) {
434448 return NOT_A_PROBABILITY ;
435449 }
436450
437-
438451 /**
439- * Loads the current binary dictionary from internal storage. Assumes the dictionary file
452+ * Loads the current binary dictionary from internal storage. Assumes the
453+ * dictionary file
440454 * exists.
441455 */
442456 void loadBinaryDictionaryLocked () {
443457 if (DBG_STRESS_TEST ) {
444- // Test if this class does not cause problems when it takes long time to load binary
458+ // Test if this class does not cause problems when it takes long time to load
459+ // binary
445460 // dictionary.
446461 try {
447462 Log .w (TAG , "Start stress in loading: " + mDictName );
@@ -493,13 +508,18 @@ boolean isNeededToRecreate() {
493508 }
494509
495510 /**
496- * Load the current binary dictionary from internal storage. If the dictionary file doesn't
497- * exists or needs to be regenerated, the new dictionary file will be asynchronously generated.
498- * However, the dictionary itself is accessible even before the new dictionary file is actually
499- * generated. It may return a null result for getSuggestions() in that case by design.
511+ * Load the current binary dictionary from internal storage. If the dictionary
512+ * file doesn't
513+ * exists or needs to be regenerated, the new dictionary file will be
514+ * asynchronously generated.
515+ * However, the dictionary itself is accessible even before the new dictionary
516+ * file is actually
517+ * generated. It may return a null result for getSuggestions() in that case by
518+ * design.
500519 */
501520 public final void reloadDictionaryIfRequired () {
502- if (!isReloadRequired ()) return ;
521+ if (!isReloadRequired ())
522+ return ;
503523 asyncReloadDictionary ();
504524 }
505525
@@ -531,7 +551,8 @@ private void asyncReloadDictionary() {
531551 final BinaryDictionary binaryDictionary = getBinaryDictionary ();
532552 if (binaryDictionary != null && !(isValidDictionaryLocked ()
533553 // TODO: remove the check below
534- && matchesExpectedBinaryDictFormatVersionForThisType (binaryDictionary .getFormatVersion ()))) {
554+ && matchesExpectedBinaryDictFormatVersionForThisType (
555+ binaryDictionary .getFormatVersion ()))) {
535556 // Binary dictionary or its format version is not valid. Regenerate
536557 // the dictionary file. createNewDictionaryLocked will remove the
537558 // existing files if appropriate.
@@ -567,8 +588,7 @@ public DictionaryStats getDictionaryStats() {
567588 reloadDictionaryIfRequired ();
568589 final String dictName = mDictName ;
569590 final File dictFile = mDictFile ;
570- final AsyncResultHolder <DictionaryStats > result =
571- new AsyncResultHolder <>("DictionaryStats" );
591+ final AsyncResultHolder <DictionaryStats > result = new AsyncResultHolder <>("DictionaryStats" );
572592 asyncExecuteTaskWithLock (mLock .readLock (), new Runnable () {
573593 @ Override
574594 public void run () {
@@ -597,8 +617,7 @@ public void dumpAllWordsForDebug() {
597617 }
598618 int token = 0 ;
599619 do {
600- final BinaryDictionary .GetNextWordPropertyResult result =
601- binaryDictionary .getNextWordProperty (token );
620+ final BinaryDictionary .GetNextWordPropertyResult result = binaryDictionary .getNextWordProperty (token );
602621 final WordProperty wordProperty = result .mWordProperty ;
603622 if (wordProperty == null ) {
604623 Log .d (tag , " dictionary is empty." );
@@ -615,8 +634,7 @@ public void dumpAllWordsForDebug() {
615634 */
616635 public WordProperty [] getWordPropertiesForSyncing () {
617636 reloadDictionaryIfRequired ();
618- final AsyncResultHolder <WordProperty []> result =
619- new AsyncResultHolder <>("WordPropertiesForSync" );
637+ final AsyncResultHolder <WordProperty []> result = new AsyncResultHolder <>("WordPropertiesForSync" );
620638 asyncExecuteTaskWithLock (mLock .readLock (), () -> {
621639 final ArrayList <WordProperty > wordPropertyList = new ArrayList <>();
622640 final BinaryDictionary binaryDictionary = getBinaryDictionary ();
@@ -626,8 +644,8 @@ public WordProperty[] getWordPropertiesForSyncing() {
626644 int token = 0 ;
627645 do {
628646 // TODO: We need a new API that returns *new* un-synced data.
629- final BinaryDictionary .GetNextWordPropertyResult nextWordPropertyResult =
630- binaryDictionary .getNextWordProperty (token );
647+ final BinaryDictionary .GetNextWordPropertyResult nextWordPropertyResult = binaryDictionary
648+ .getNextWordProperty (token );
631649 final WordProperty wordProperty = nextWordPropertyResult .mWordProperty ;
632650 if (wordProperty == null ) {
633651 break ;
0 commit comments