Use dictType to class map to create sub dicts.

Bug: 13755213
Change-Id: I4dcd5684bc65f13361bf9c4f9d50b07b1e33c62d
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 30b3433..9bc01a2 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -29,6 +29,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.personalization.AccountUtils;
 import com.android.inputmethod.latin.utils.StringUtils;
 
@@ -82,6 +83,7 @@
         reloadDictionaryIfRequired();
     }
 
+    @UsedForTesting
     public static ContactsBinaryDictionary getDictionary(final Context context, final Locale locale,
             final File dictFile) {
         return new ContactsBinaryDictionary(context, locale, dictFile);
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
index 0619107..39b045b 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
@@ -31,6 +31,8 @@
 import com.android.inputmethod.latin.utils.SuggestionResults;
 
 import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -64,6 +66,20 @@
                 Dictionary.TYPE_CONTACTS
             };
 
+    private static final Map<String, Class<? extends ExpandableBinaryDictionary>>
+            DICT_TYPE_TO_CLASS = CollectionUtils.newHashMap();
+
+    static {
+        DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_USER_HISTORY, UserHistoryDictionary.class);
+        DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_PERSONALIZATION, PersonalizationDictionary.class);
+        DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_USER, UserBinaryDictionary.class);
+        DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_CONTACTS, ContactsBinaryDictionary.class);
+    }
+
+    private static final String DICT_FACTORY_METHOD_NAME = "getDictionary";
+    private static final Class<?>[] DICT_FACTORY_METHOD_ARG_TYPES =
+            new Class[] { Context.class, Locale.class, File.class };
+
     private static final String[] SUB_DICT_TYPES =
             Arrays.copyOfRange(DICT_TYPES_ORDERED_TO_GET_SUGGESTION, 1 /* start */,
                     DICT_TYPES_ORDERED_TO_GET_SUGGESTION.length);
@@ -145,15 +161,20 @@
 
     private static ExpandableBinaryDictionary getSubDict(final String dictType,
             final Context context, final Locale locale, final File dictFile) {
-        if (Dictionary.TYPE_CONTACTS.equals(dictType)) {
-            return ContactsBinaryDictionary.getDictionary(context, locale, dictFile);
-        } else if (Dictionary.TYPE_USER.equals(dictType)) {
-            return UserBinaryDictionary.getDictionary(context, locale, dictFile);
-        } else if (Dictionary.TYPE_USER_HISTORY.equals(dictType)) {
-            return UserHistoryDictionary.getDictionary(context, locale, dictFile);
-        } else if (Dictionary.TYPE_PERSONALIZATION.equals(dictType)) {
-            return PersonalizationDictionary.getDictionary(context, locale, dictFile);
-        } else {
+        final Class<? extends ExpandableBinaryDictionary> dictClass =
+                DICT_TYPE_TO_CLASS.get(dictType);
+        if (dictClass == null) {
+            return null;
+        }
+        try {
+            final Method factoryMethod = dictClass.getMethod(DICT_FACTORY_METHOD_NAME,
+                    DICT_FACTORY_METHOD_ARG_TYPES);
+            final Object dict = factoryMethod.invoke(null /* obj */,
+                    new Object[] { context, locale, dictFile });
+            return (ExpandableBinaryDictionary) dict;
+        } catch (final NoSuchMethodException | SecurityException | IllegalAccessException
+                | IllegalArgumentException | InvocationTargetException e) {
+            Log.e(TAG, "Cannot create dictionary: " + dictType, e);
             return null;
         }
     }
@@ -165,9 +186,10 @@
         final boolean localeHasBeenChanged = !newLocale.equals(mDictionaries.mLocale);
         // We always try to have the main dictionary. Other dictionaries can be unused.
         final boolean reloadMainDictionary = localeHasBeenChanged || forceReloadMainDictionary;
+        // TODO: Make subDictTypesToUse configurable by resource or a static final list.
         final Set<String> subDictTypesToUse = CollectionUtils.newHashSet();
         if (useContactsDict) {
-            subDictTypesToUse.add(Dictionary.TYPE_USER);
+            subDictTypesToUse.add(Dictionary.TYPE_CONTACTS);
         }
         subDictTypesToUse.add(Dictionary.TYPE_USER);
         if (usePersonalizedDicts) {
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
index 6a9f3ac..0a9dae4 100644
--- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -28,6 +28,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.compat.UserDictionaryCompatUtils;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
@@ -112,6 +113,7 @@
         reloadDictionaryIfRequired();
     }
 
+    @UsedForTesting
     public static UserBinaryDictionary getDictionary(final Context context, final Locale locale,
             final File dictFile) {
         return new UserBinaryDictionary(context, locale, dictFile);
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
index 3f879f0..1423fce 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 
+import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.Dictionary;
 
 import java.io.File;
@@ -32,6 +33,7 @@
                 Dictionary.TYPE_PERSONALIZATION, null /* dictFile */);
     }
 
+    @UsedForTesting
     public static PersonalizationDictionary getDictionary(final Context context,
             final Locale locale, final File dictFile) {
         return PersonalizationHelper.getPersonalizationDictionary(context, locale);
diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
index 36e59e9..818cd9a 100644
--- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 
+import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.Dictionary;
 import com.android.inputmethod.latin.ExpandableBinaryDictionary;
@@ -38,6 +39,7 @@
                 Dictionary.TYPE_USER_HISTORY, null /* dictFile */);
     }
 
+    @UsedForTesting
     public static UserHistoryDictionary getDictionary(final Context context, final Locale locale,
             final File dictFile) {
         return PersonalizationHelper.getUserHistoryDictionary(context, locale);