aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Chalard <jchalard@google.com>2013-01-29 18:05:33 +0900
committerJean Chalard <jchalard@google.com>2013-01-29 19:16:21 +0900
commitd515f134f726c432c0bab5600e7b31ed989fb1b5 (patch)
treef11ed68872c7324e27d9144ab497a77615f0cc3a
parent19e13df91f36cf131f5139c44d7b80fc1e8f6f21 (diff)
downloadlatinime-d515f134f726c432c0bab5600e7b31ed989fb1b5.tar.gz
latinime-d515f134f726c432c0bab5600e7b31ed989fb1b5.tar.xz
latinime-d515f134f726c432c0bab5600e7b31ed989fb1b5.zip
Refactoring
This creates a new DictionaryInfoUtils class and moves a bunch of static methods there for later usage. Change-Id: Iecb0643e6029a7be36bd6cb36aa918c40e6d8c6a
-rw-r--r--java/src/com/android/inputmethod/latin/AssetFileAddress.java9
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java2
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java169
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFactory.java51
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java245
-rw-r--r--java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java20
6 files changed, 274 insertions, 222 deletions
diff --git a/java/src/com/android/inputmethod/latin/AssetFileAddress.java b/java/src/com/android/inputmethod/latin/AssetFileAddress.java
index 16296f0e2..47c750f54 100644
--- a/java/src/com/android/inputmethod/latin/AssetFileAddress.java
+++ b/java/src/com/android/inputmethod/latin/AssetFileAddress.java
@@ -35,11 +35,14 @@ final class AssetFileAddress {
mLength = length;
}
+ public static AssetFileAddress makeFromFile(final File file) {
+ if (!file.isFile()) return null;
+ return new AssetFileAddress(file.getAbsolutePath(), 0L, file.length());
+ }
+
public static AssetFileAddress makeFromFileName(final String filename) {
if (null == filename) return null;
- final File f = new File(filename);
- if (!f.isFile()) return null;
- return new AssetFileAddress(filename, 0l, f.length());
+ return makeFromFile(new File(filename));
}
public static AssetFileAddress makeFromFileNameAndOffset(final String filename,
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index d0bd01f6b..443ffa2e9 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -149,7 +149,7 @@ public final class BinaryDictionaryFileDumper {
final int MODE_MAX = NONE;
final Uri.Builder wordListUriBuilder = getProviderUriBuilder(id);
- final String finalFileName = BinaryDictionaryGetter.getCacheFileName(id, locale, context);
+ final String finalFileName = DictionaryInfoUtils.getCacheFileName(id, locale, context);
String tempFileName;
try {
tempFileName = BinaryDictionaryGetter.getTempFileName(id, context);
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index 22b5cd55c..5da0f1be8 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -66,109 +66,11 @@ final class BinaryDictionaryGetter {
private BinaryDictionaryGetter() {}
/**
- * Returns whether we may want to use this character as part of a file name.
- *
- * This basically only accepts ascii letters and numbers, and rejects everything else.
- */
- private static boolean isFileNameCharacter(int codePoint) {
- if (codePoint >= 0x30 && codePoint <= 0x39) return true; // Digit
- if (codePoint >= 0x41 && codePoint <= 0x5A) return true; // Uppercase
- if (codePoint >= 0x61 && codePoint <= 0x7A) return true; // Lowercase
- return codePoint == '_'; // Underscore
- }
-
- /**
- * Escapes a string for any characters that may be suspicious for a file or directory name.
- *
- * Concretely this does a sort of URL-encoding except it will encode everything that's not
- * alphanumeric or underscore. (true URL-encoding leaves alone characters like '*', which
- * we cannot allow here)
- */
- // TODO: create a unit test for this method
- private static String replaceFileNameDangerousCharacters(final String name) {
- // This assumes '%' is fully available as a non-separator, normal
- // character in a file name. This is probably true for all file systems.
- final StringBuilder sb = new StringBuilder();
- final int nameLength = name.length();
- for (int i = 0; i < nameLength; i = name.offsetByCodePoints(i, 1)) {
- final int codePoint = name.codePointAt(i);
- if (isFileNameCharacter(codePoint)) {
- sb.appendCodePoint(codePoint);
- } else {
- // 6 digits - unicode is limited to 21 bits
- sb.append(String.format((Locale)null, "%%%1$06x", codePoint));
- }
- }
- return sb.toString();
- }
-
- /**
- * Reverse escaping done by replaceFileNameDangerousCharacters.
- */
- private static String getWordListIdFromFileName(final String fname) {
- final StringBuilder sb = new StringBuilder();
- final int fnameLength = fname.length();
- for (int i = 0; i < fnameLength; i = fname.offsetByCodePoints(i, 1)) {
- final int codePoint = fname.codePointAt(i);
- if ('%' != codePoint) {
- sb.appendCodePoint(codePoint);
- } else {
- final int encodedCodePoint = Integer.parseInt(fname.substring(i + 1, i + 7), 16);
- i += 6;
- sb.appendCodePoint(encodedCodePoint);
- }
- }
- return sb.toString();
- }
-
- /**
- * Helper method to get the top level cache directory.
- */
- private static String getWordListCacheDirectory(final Context context) {
- return context.getFilesDir() + File.separator + "dicts";
- }
-
- /**
- * Find out the cache directory associated with a specific locale.
- */
- private static String getCacheDirectoryForLocale(final String locale, final Context context) {
- final String relativeDirectoryName = replaceFileNameDangerousCharacters(locale);
- final String absoluteDirectoryName = getWordListCacheDirectory(context) + File.separator
- + relativeDirectoryName;
- final File directory = new File(absoluteDirectoryName);
- if (!directory.exists()) {
- if (!directory.mkdirs()) {
- Log.e(TAG, "Could not create the directory for locale" + locale);
- }
- }
- return absoluteDirectoryName;
- }
-
- /**
- * Generates a file name for the id and locale passed as an argument.
- *
- * In the current implementation the file name returned will always be unique for
- * any id/locale pair, but please do not expect that the id can be the same for
- * different dictionaries with different locales. An id should be unique for any
- * dictionary.
- * The file name is pretty much an URL-encoded version of the id inside a directory
- * named like the locale, except it will also escape characters that look dangerous
- * to some file systems.
- * @param id the id of the dictionary for which to get a file name
- * @param locale the locale for which to get the file name as a string
- * @param context the context to use for getting the directory
- * @return the name of the file to be created
- */
- public static String getCacheFileName(String id, String locale, Context context) {
- final String fileName = replaceFileNameDangerousCharacters(id);
- return getCacheDirectoryForLocale(locale, context) + File.separator + fileName;
- }
-
- /**
* Generates a unique temporary file name in the app cache directory.
*/
public static String getTempFileName(String id, Context context) throws IOException {
- return File.createTempFile(replaceFileNameDangerousCharacters(id), null).getAbsolutePath();
+ return File.createTempFile(DictionaryInfoUtils.replaceFileNameDangerousCharacters(id),
+ null).getAbsolutePath();
}
/**
@@ -222,27 +124,6 @@ final class BinaryDictionaryGetter {
}
/**
- * Helper method to the list of cache directories, one for each distinct locale.
- */
- private static File[] getCachedDirectoryList(final Context context) {
- return new File(getWordListCacheDirectory(context)).listFiles();
- }
-
- /**
- * Returns the category for a given file name.
- *
- * This parses the file name, extracts the category, and returns it. See
- * {@link #getMainDictId(Locale)} and {@link #isMainWordListId(String)}.
- * @return The category as a string or null if it can't be found in the file name.
- */
- private static String getCategoryFromFileName(final String fileName) {
- final String id = getWordListIdFromFileName(fileName);
- final String[] idArray = id.split(ID_CATEGORY_SEPARATOR);
- if (2 != idArray.length) return null;
- return idArray[0];
- }
-
- /**
* Utility class for the {@link #getCachedWordLists} method
*/
private static final class FileAndMatchLevel {
@@ -268,20 +149,21 @@ final class BinaryDictionaryGetter {
* @param context the context on which to open the files upon.
* @return an array of binary dictionary files, which may be empty but may not be null.
*/
- private static File[] getCachedWordLists(final String locale,
- final Context context) {
- final File[] directoryList = getCachedDirectoryList(context);
+ private static File[] getCachedWordLists(final String locale, final Context context) {
+ final File[] directoryList = DictionaryInfoUtils.getCachedDirectoryList(context);
if (null == directoryList) return EMPTY_FILE_ARRAY;
final HashMap<String, FileAndMatchLevel> cacheFiles = CollectionUtils.newHashMap();
for (File directory : directoryList) {
if (!directory.isDirectory()) continue;
- final String dirLocale = getWordListIdFromFileName(directory.getName());
+ final String dirLocale =
+ DictionaryInfoUtils.getWordListIdFromFileName(directory.getName());
final int matchLevel = LocaleUtils.getMatchLevel(dirLocale, locale);
if (LocaleUtils.isMatch(matchLevel)) {
final File[] wordLists = directory.listFiles();
if (null != wordLists) {
for (File wordList : wordLists) {
- final String category = getCategoryFromFileName(wordList.getName());
+ final String category =
+ DictionaryInfoUtils.getCategoryFromFileName(wordList.getName());
final FileAndMatchLevel currentBestMatch = cacheFiles.get(category);
if (null == currentBestMatch || currentBestMatch.mMatchLevel < matchLevel) {
cacheFiles.put(category, new FileAndMatchLevel(wordList, matchLevel));
@@ -310,7 +192,7 @@ final class BinaryDictionaryGetter {
final File fileToKeep) {
try {
final File canonicalFileToKeep = fileToKeep.getCanonicalFile();
- final File[] directoryList = getCachedDirectoryList(context);
+ final File[] directoryList = DictionaryInfoUtils.getCachedDirectoryList(context);
if (null == directoryList) return;
for (File directory : directoryList) {
// There is one directory per locale. See #getCachedDirectoryList
@@ -318,7 +200,8 @@ final class BinaryDictionaryGetter {
final File[] wordLists = directory.listFiles();
if (null == wordLists) continue;
for (File wordList : wordLists) {
- final String fileId = getWordListIdFromFileName(wordList.getName());
+ final String fileId =
+ DictionaryInfoUtils.getWordListIdFromFileName(wordList.getName());
if (fileId.equals(id)) {
if (!canonicalFileToKeep.equals(wordList.getCanonicalFile())) {
wordList.delete();
@@ -331,28 +214,6 @@ final class BinaryDictionaryGetter {
}
}
-
- /**
- * Returns the id associated with the main word list for a specified locale.
- *
- * Word lists stored in Android Keyboard's resources are referred to as the "main"
- * word lists. Since they can be updated like any other list, we need to assign a
- * unique ID to them. This ID is just the name of the language (locale-wise) they
- * are for, and this method returns this ID.
- */
- private static String getMainDictId(final Locale locale) {
- // This works because we don't include by default different dictionaries for
- // different countries. This actually needs to return the id that we would
- // like to use for word lists included in resources, and the following is okay.
- return MAIN_DICTIONARY_CATEGORY + ID_CATEGORY_SEPARATOR + locale.getLanguage().toString();
- }
-
- private static boolean isMainWordListId(final String id) {
- final String[] idArray = id.split(ID_CATEGORY_SEPARATOR);
- if (2 != idArray.length) return false;
- return MAIN_DICTIONARY_CATEGORY.equals(idArray[0]);
- }
-
// ## HACK ## we prevent usage of a dictionary before version 18 for English only. The reason
// for this is, since those do not include whitelist entries, the new code with an old version
// of the dictionary would lose whitelist functionality.
@@ -429,16 +290,16 @@ final class BinaryDictionaryGetter {
hasDefaultWordList);
}
final File[] cachedWordLists = getCachedWordLists(locale.toString(), context);
- final String mainDictId = getMainDictId(locale);
+ final String mainDictId = DictionaryInfoUtils.getMainDictId(locale);
final DictPackSettings dictPackSettings = new DictPackSettings(context);
boolean foundMainDict = false;
final ArrayList<AssetFileAddress> fileList = CollectionUtils.newArrayList();
// cachedWordLists may not be null, see doc for getCachedDictionaryList
for (final File f : cachedWordLists) {
- final String wordListId = getWordListIdFromFileName(f.getName());
+ final String wordListId = DictionaryInfoUtils.getWordListIdFromFileName(f.getName());
final boolean canUse = f.canRead() && hackCanUseDictionaryFile(locale, f);
- if (canUse && isMainWordListId(wordListId)) {
+ if (canUse && DictionaryInfoUtils.isMainWordListId(wordListId)) {
foundMainDict = true;
}
if (!dictPackSettings.isWordListActive(wordListId)) continue;
@@ -451,7 +312,7 @@ final class BinaryDictionaryGetter {
if (!foundMainDict && dictPackSettings.isWordListActive(mainDictId)) {
final int fallbackResId =
- DictionaryFactory.getMainDictionaryResourceId(context.getResources(), locale);
+ DictionaryInfoUtils.getMainDictionaryResourceId(context.getResources(), locale);
final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId);
if (null != fallbackAsset) {
fileList.add(fallbackAsset);
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
index 388ad6c59..40e51672a 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
@@ -31,9 +31,6 @@ import java.util.Locale;
*/
public final class DictionaryFactory {
private static final String TAG = DictionaryFactory.class.getSimpleName();
- // This class must be located in the same package as LatinIME.java.
- private static final String RESOURCE_PACKAGE_NAME =
- DictionaryFactory.class.getPackage().getName();
/**
* Initializes a main dictionary collection from a dictionary pack, with explicit flags.
@@ -96,8 +93,8 @@ public final class DictionaryFactory {
final Locale locale) {
AssetFileDescriptor afd = null;
try {
- final int resId =
- getMainDictionaryResourceIdIfAvailableForLocale(context.getResources(), locale);
+ final int resId = DictionaryInfoUtils.getMainDictionaryResourceIdIfAvailableForLocale(
+ context.getResources(), locale);
if (0 == resId) return null;
afd = context.getResources().openRawResourceFd(resId);
if (afd == null) {
@@ -154,47 +151,7 @@ public final class DictionaryFactory {
*/
public static boolean isDictionaryAvailable(Context context, Locale locale) {
final Resources res = context.getResources();
- return 0 != getMainDictionaryResourceIdIfAvailableForLocale(res, locale);
- }
-
- private static final String DEFAULT_MAIN_DICT = "main";
- private static final String MAIN_DICT_PREFIX = "main_";
-
- /**
- * Helper method to return a dictionary res id for a locale, or 0 if none.
- * @param locale dictionary locale
- * @return main dictionary resource id
- */
- private static int getMainDictionaryResourceIdIfAvailableForLocale(final Resources res,
- final Locale locale) {
- int resId;
- // Try to find main_language_country dictionary.
- if (!locale.getCountry().isEmpty()) {
- final String dictLanguageCountry = MAIN_DICT_PREFIX + locale.toString().toLowerCase();
- if ((resId = res.getIdentifier(
- dictLanguageCountry, "raw", RESOURCE_PACKAGE_NAME)) != 0) {
- return resId;
- }
- }
-
- // Try to find main_language dictionary.
- final String dictLanguage = MAIN_DICT_PREFIX + locale.getLanguage();
- if ((resId = res.getIdentifier(dictLanguage, "raw", RESOURCE_PACKAGE_NAME)) != 0) {
- return resId;
- }
-
- // Not found, return 0
- return 0;
- }
-
- /**
- * Returns a main dictionary resource id
- * @param locale dictionary locale
- * @return main dictionary resource id
- */
- public static int getMainDictionaryResourceId(final Resources res, final Locale locale) {
- int resourceId = getMainDictionaryResourceIdIfAvailableForLocale(res, locale);
- if (0 != resourceId) return resourceId;
- return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", RESOURCE_PACKAGE_NAME);
+ return 0 != DictionaryInfoUtils.getMainDictionaryResourceIdIfAvailableForLocale(
+ res, locale);
}
}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java
new file mode 100644
index 000000000..c676bf1b9
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+import com.android.inputmethod.latin.makedict.BinaryDictIOUtils;
+import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
+import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Locale;
+
+/**
+ * This class encapsulates the logic for the Latin-IME side of dictionary information management.
+ */
+public class DictionaryInfoUtils {
+ private static final String TAG = DictionaryInfoUtils.class.getSimpleName();
+ // This class must be located in the same package as LatinIME.java.
+ private static final String RESOURCE_PACKAGE_NAME =
+ DictionaryInfoUtils.class.getPackage().getName();
+ private static final String DEFAULT_MAIN_DICT = "main";
+ private static final String MAIN_DICT_PREFIX = "main_";
+ // 6 digits - unicode is limited to 21 bits
+ private static final int MAX_HEX_DIGITS_FOR_CODEPOINT = 6;
+
+ private DictionaryInfoUtils() {
+ // Private constructor to forbid instantation of this helper class.
+ }
+
+ /**
+ * Returns whether we may want to use this character as part of a file name.
+ *
+ * This basically only accepts ascii letters and numbers, and rejects everything else.
+ */
+ private static boolean isFileNameCharacter(int codePoint) {
+ if (codePoint >= 0x30 && codePoint <= 0x39) return true; // Digit
+ if (codePoint >= 0x41 && codePoint <= 0x5A) return true; // Uppercase
+ if (codePoint >= 0x61 && codePoint <= 0x7A) return true; // Lowercase
+ return codePoint == '_'; // Underscore
+ }
+
+ /**
+ * Escapes a string for any characters that may be suspicious for a file or directory name.
+ *
+ * Concretely this does a sort of URL-encoding except it will encode everything that's not
+ * alphanumeric or underscore. (true URL-encoding leaves alone characters like '*', which
+ * we cannot allow here)
+ */
+ // TODO: create a unit test for this method
+ public static String replaceFileNameDangerousCharacters(final String name) {
+ // This assumes '%' is fully available as a non-separator, normal
+ // character in a file name. This is probably true for all file systems.
+ final StringBuilder sb = new StringBuilder();
+ final int nameLength = name.length();
+ for (int i = 0; i < nameLength; i = name.offsetByCodePoints(i, 1)) {
+ final int codePoint = name.codePointAt(i);
+ if (DictionaryInfoUtils.isFileNameCharacter(codePoint)) {
+ sb.appendCodePoint(codePoint);
+ } else {
+ sb.append(String.format((Locale)null, "%%%1$0" + MAX_HEX_DIGITS_FOR_CODEPOINT + "x",
+ codePoint));
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Helper method to get the top level cache directory.
+ */
+ private static String getWordListCacheDirectory(final Context context) {
+ return context.getFilesDir() + File.separator + "dicts";
+ }
+
+ /**
+ * Reverse escaping done by replaceFileNameDangerousCharacters.
+ */
+ public static String getWordListIdFromFileName(final String fname) {
+ final StringBuilder sb = new StringBuilder();
+ final int fnameLength = fname.length();
+ for (int i = 0; i < fnameLength; i = fname.offsetByCodePoints(i, 1)) {
+ final int codePoint = fname.codePointAt(i);
+ if ('%' != codePoint) {
+ sb.appendCodePoint(codePoint);
+ } else {
+ // + 1 to pass the % sign
+ final int encodedCodePoint = Integer.parseInt(
+ fname.substring(i + 1, i + 1 + MAX_HEX_DIGITS_FOR_CODEPOINT), 16);
+ i += MAX_HEX_DIGITS_FOR_CODEPOINT;
+ sb.appendCodePoint(encodedCodePoint);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Helper method to the list of cache directories, one for each distinct locale.
+ */
+ public static File[] getCachedDirectoryList(final Context context) {
+ return new File(DictionaryInfoUtils.getWordListCacheDirectory(context)).listFiles();
+ }
+
+ /**
+ * Returns the category for a given file name.
+ *
+ * This parses the file name, extracts the category, and returns it. See
+ * {@link #getMainDictId(Locale)} and {@link #isMainWordListId(String)}.
+ * @return The category as a string or null if it can't be found in the file name.
+ */
+ public static String getCategoryFromFileName(final String fileName) {
+ final String id = getWordListIdFromFileName(fileName);
+ final String[] idArray = id.split(BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR);
+ // An id is supposed to be in format category:locale, so splitting on the separator
+ // should yield a 2-elements array
+ if (2 != idArray.length) return null;
+ return idArray[0];
+ }
+
+ /**
+ * Find out the cache directory associated with a specific locale.
+ */
+ private static String getCacheDirectoryForLocale(final String locale, final Context context) {
+ final String relativeDirectoryName = replaceFileNameDangerousCharacters(locale);
+ final String absoluteDirectoryName = getWordListCacheDirectory(context) + File.separator
+ + relativeDirectoryName;
+ final File directory = new File(absoluteDirectoryName);
+ if (!directory.exists()) {
+ if (!directory.mkdirs()) {
+ Log.e(TAG, "Could not create the directory for locale" + locale);
+ }
+ }
+ return absoluteDirectoryName;
+ }
+
+ /**
+ * Generates a file name for the id and locale passed as an argument.
+ *
+ * In the current implementation the file name returned will always be unique for
+ * any id/locale pair, but please do not expect that the id can be the same for
+ * different dictionaries with different locales. An id should be unique for any
+ * dictionary.
+ * The file name is pretty much an URL-encoded version of the id inside a directory
+ * named like the locale, except it will also escape characters that look dangerous
+ * to some file systems.
+ * @param id the id of the dictionary for which to get a file name
+ * @param locale the locale for which to get the file name as a string
+ * @param context the context to use for getting the directory
+ * @return the name of the file to be created
+ */
+ public static String getCacheFileName(String id, String locale, Context context) {
+ final String fileName = replaceFileNameDangerousCharacters(id);
+ return getCacheDirectoryForLocale(locale, context) + File.separator + fileName;
+ }
+
+ public static boolean isMainWordListId(final String id) {
+ final String[] idArray = id.split(BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR);
+ // An id is supposed to be in format category:locale, so splitting on the separator
+ // should yield a 2-elements array
+ if (2 != idArray.length) return false;
+ return BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY.equals(idArray[0]);
+ }
+
+ /**
+ * Helper method to return a dictionary res id for a locale, or 0 if none.
+ * @param locale dictionary locale
+ * @return main dictionary resource id
+ */
+ public static int getMainDictionaryResourceIdIfAvailableForLocale(final Resources res,
+ final Locale locale) {
+ int resId;
+ // Try to find main_language_country dictionary.
+ if (!locale.getCountry().isEmpty()) {
+ final String dictLanguageCountry =
+ MAIN_DICT_PREFIX + locale.toString().toLowerCase(Locale.ROOT);
+ if ((resId = res.getIdentifier(
+ dictLanguageCountry, "raw", RESOURCE_PACKAGE_NAME)) != 0) {
+ return resId;
+ }
+ }
+
+ // Try to find main_language dictionary.
+ final String dictLanguage = MAIN_DICT_PREFIX + locale.getLanguage();
+ if ((resId = res.getIdentifier(dictLanguage, "raw", RESOURCE_PACKAGE_NAME)) != 0) {
+ return resId;
+ }
+
+ // Not found, return 0
+ return 0;
+ }
+
+ /**
+ * Returns a main dictionary resource id
+ * @param locale dictionary locale
+ * @return main dictionary resource id
+ */
+ public static int getMainDictionaryResourceId(final Resources res, final Locale locale) {
+ int resourceId = getMainDictionaryResourceIdIfAvailableForLocale(res, locale);
+ if (0 != resourceId) return resourceId;
+ return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", RESOURCE_PACKAGE_NAME);
+ }
+
+ /**
+ * Returns the id associated with the main word list for a specified locale.
+ *
+ * Word lists stored in Android Keyboard's resources are referred to as the "main"
+ * word lists. Since they can be updated like any other list, we need to assign a
+ * unique ID to them. This ID is just the name of the language (locale-wise) they
+ * are for, and this method returns this ID.
+ */
+ public static String getMainDictId(final Locale locale) {
+ // This works because we don't include by default different dictionaries for
+ // different countries. This actually needs to return the id that we would
+ // like to use for word lists included in resources, and the following is okay.
+ return BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY +
+ BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + locale.getLanguage().toString();
+ }
+
+ public static FileHeader getDictionaryFileHeaderOrNull(final File file) {
+ try {
+ final FileHeader header = BinaryDictIOUtils.getDictionaryFileHeader(file);
+ return header;
+ } catch (UnsupportedFormatException e) {
+ return null;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java b/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java
index 6e5a37c72..d9e4bb63d 100644
--- a/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java
+++ b/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java
@@ -21,11 +21,8 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Environment;
-import android.util.Log;
-import com.android.inputmethod.latin.makedict.BinaryDictIOUtils;
import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
-import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -44,22 +41,11 @@ public class ExternalDictionaryGetterForDebug {
+ "/Download";
private static final String DICTIONARY_LOCALE_ATTRIBUTE = "locale";
- private static FileHeader getDictionaryFileHeaderOrNull(final File file) {
- try {
- final FileHeader header = BinaryDictIOUtils.getDictionaryFileHeader(file);
- return header;
- } catch (UnsupportedFormatException e) {
- return null;
- } catch (IOException e) {
- return null;
- }
- }
-
private static String[] findDictionariesInTheDownloadedFolder() {
final File[] files = new File(SOURCE_FOLDER).listFiles();
final ArrayList<String> eligibleList = CollectionUtils.newArrayList();
for (File f : files) {
- final FileHeader header = getDictionaryFileHeaderOrNull(f);
+ final FileHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(f);
if (null == header) continue;
eligibleList.add(f.getName());
}
@@ -102,7 +88,7 @@ public class ExternalDictionaryGetterForDebug {
private static void askInstallFile(final Context context, final String fileName) {
final File file = new File(SOURCE_FOLDER, fileName.toString());
- final FileHeader header = getDictionaryFileHeaderOrNull(file);
+ final FileHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(file);
final StringBuilder message = new StringBuilder();
final String locale =
header.mDictionaryOptions.mAttributes.get(DICTIONARY_LOCALE_ATTRIBUTE);
@@ -143,7 +129,7 @@ public class ExternalDictionaryGetterForDebug {
final String id = BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY
+ BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + locale;
final String finalFileName =
- BinaryDictionaryGetter.getCacheFileName(id, locale, context);
+ DictionaryInfoUtils.getCacheFileName(id, locale, context);
final String tempFileName = BinaryDictionaryGetter.getTempFileName(id, context);
tempFile = new File(tempFileName);
tempFile.delete();