aboutsummaryrefslogtreecommitdiffstats
path: root/common/src/com/android/inputmethod/latin
diff options
context:
space:
mode:
Diffstat (limited to 'common/src/com/android/inputmethod/latin')
-rw-r--r--common/src/com/android/inputmethod/latin/common/CollectionUtils.java63
-rw-r--r--common/src/com/android/inputmethod/latin/common/CoordinateUtils.java94
-rw-r--r--common/src/com/android/inputmethod/latin/common/FileUtils.java54
-rw-r--r--common/src/com/android/inputmethod/latin/common/LocaleUtils.java185
4 files changed, 396 insertions, 0 deletions
diff --git a/common/src/com/android/inputmethod/latin/common/CollectionUtils.java b/common/src/com/android/inputmethod/latin/common/CollectionUtils.java
new file mode 100644
index 000000000..f7ba693af
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/CollectionUtils.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 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.common;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * Utility methods for working with collections.
+ */
+public final class CollectionUtils {
+ private CollectionUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ /**
+ * Converts a sub-range of the given array to an ArrayList of the appropriate type.
+ * @param array Array to be converted.
+ * @param start First index inclusive to be converted.
+ * @param end Last index exclusive to be converted.
+ * @throws IllegalArgumentException if start or end are out of range or start > end.
+ */
+ @Nonnull
+ public static <E> ArrayList<E> arrayAsList(@Nonnull final E[] array, final int start,
+ final int end) {
+ if (start < 0 || start > end || end > array.length) {
+ throw new IllegalArgumentException("Invalid start: " + start + " end: " + end
+ + " with array.length: " + array.length);
+ }
+
+ final ArrayList<E> list = new ArrayList<>(end - start);
+ for (int i = start; i < end; i++) {
+ list.add(array[i]);
+ }
+ return list;
+ }
+
+ /**
+ * Tests whether c contains no elements, true if c is null or c is empty.
+ * @param c Collection to test.
+ * @return Whether c contains no elements.
+ */
+ public static boolean isNullOrEmpty(@Nullable final Collection<?> c) {
+ return c == null || c.isEmpty();
+ }
+}
diff --git a/common/src/com/android/inputmethod/latin/common/CoordinateUtils.java b/common/src/com/android/inputmethod/latin/common/CoordinateUtils.java
new file mode 100644
index 000000000..031662411
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/CoordinateUtils.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 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.common;
+
+import javax.annotation.Nonnull;
+
+public final class CoordinateUtils {
+ private static final int INDEX_X = 0;
+ private static final int INDEX_Y = 1;
+ private static final int ELEMENT_SIZE = INDEX_Y + 1;
+
+ private CoordinateUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ @Nonnull
+ public static int[] newInstance() {
+ return new int[ELEMENT_SIZE];
+ }
+
+ public static int x(@Nonnull final int[] coords) {
+ return coords[INDEX_X];
+ }
+
+ public static int y(@Nonnull final int[] coords) {
+ return coords[INDEX_Y];
+ }
+
+ public static void set(@Nonnull final int[] coords, final int x, final int y) {
+ coords[INDEX_X] = x;
+ coords[INDEX_Y] = y;
+ }
+
+ public static void copy(@Nonnull final int[] destination, @Nonnull final int[] source) {
+ destination[INDEX_X] = source[INDEX_X];
+ destination[INDEX_Y] = source[INDEX_Y];
+ }
+
+ @Nonnull
+ public static int[] newCoordinateArray(final int arraySize) {
+ return new int[ELEMENT_SIZE * arraySize];
+ }
+
+ @Nonnull
+ public static int[] newCoordinateArray(final int arraySize,
+ final int defaultX, final int defaultY) {
+ final int[] result = new int[ELEMENT_SIZE * arraySize];
+ for (int i = 0; i < arraySize; ++i) {
+ setXYInArray(result, i, defaultX, defaultY);
+ }
+ return result;
+ }
+
+ public static int xFromArray(@Nonnull final int[] coordsArray, final int index) {
+ return coordsArray[ELEMENT_SIZE * index + INDEX_X];
+ }
+
+ public static int yFromArray(@Nonnull final int[] coordsArray, final int index) {
+ return coordsArray[ELEMENT_SIZE * index + INDEX_Y];
+ }
+
+ @Nonnull
+ public static int[] coordinateFromArray(@Nonnull final int[] coordsArray, final int index) {
+ final int[] coords = newInstance();
+ set(coords, xFromArray(coordsArray, index), yFromArray(coordsArray, index));
+ return coords;
+ }
+
+ public static void setXYInArray(@Nonnull final int[] coordsArray, final int index,
+ final int x, final int y) {
+ final int baseIndex = ELEMENT_SIZE * index;
+ coordsArray[baseIndex + INDEX_X] = x;
+ coordsArray[baseIndex + INDEX_Y] = y;
+ }
+
+ public static void setCoordinateInArray(@Nonnull final int[] coordsArray, final int index,
+ @Nonnull final int[] coords) {
+ setXYInArray(coordsArray, index, x(coords), y(coords));
+ }
+}
diff --git a/common/src/com/android/inputmethod/latin/common/FileUtils.java b/common/src/com/android/inputmethod/latin/common/FileUtils.java
new file mode 100644
index 000000000..676845842
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/FileUtils.java
@@ -0,0 +1,54 @@
+/*
+ * 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.common;
+
+import java.io.File;
+import java.io.FilenameFilter;
+
+/**
+ * A simple class to help with removing directories recursively.
+ */
+public class FileUtils {
+ public static boolean deleteRecursively(final File path) {
+ if (path.isDirectory()) {
+ final File[] files = path.listFiles();
+ if (files != null) {
+ for (final File child : files) {
+ deleteRecursively(child);
+ }
+ }
+ }
+ return path.delete();
+ }
+
+ public static boolean deleteFilteredFiles(final File dir, final FilenameFilter fileNameFilter) {
+ if (!dir.isDirectory()) {
+ return false;
+ }
+ final File[] files = dir.listFiles(fileNameFilter);
+ if (files == null) {
+ return false;
+ }
+ boolean hasDeletedAllFiles = true;
+ for (final File file : files) {
+ if (!deleteRecursively(file)) {
+ hasDeletedAllFiles = false;
+ }
+ }
+ return hasDeletedAllFiles;
+ }
+}
diff --git a/common/src/com/android/inputmethod/latin/common/LocaleUtils.java b/common/src/com/android/inputmethod/latin/common/LocaleUtils.java
new file mode 100644
index 000000000..14b3d220d
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/LocaleUtils.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2011 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.common;
+
+import java.util.HashMap;
+import java.util.Locale;
+
+/**
+ * A class to help with handling Locales in string form.
+ *
+ * This file has the same meaning and features (and shares all of its code) with the one with the
+ * same name in Latin IME. They need to be kept synchronized; for any update/bugfix to
+ * this file, consider also updating/fixing the version in Latin IME.
+ */
+public final class LocaleUtils {
+ private LocaleUtils() {
+ // Intentional empty constructor for utility class.
+ }
+
+ // Locale match level constants.
+ // A higher level of match is guaranteed to have a higher numerical value.
+ // Some room is left within constants to add match cases that may arise necessary
+ // in the future, for example differentiating between the case where the countries
+ // are both present and different, and the case where one of the locales does not
+ // specify the countries. This difference is not needed now.
+
+ // Nothing matches.
+ public static final int LOCALE_NO_MATCH = 0;
+ // The languages matches, but the country are different. Or, the reference locale requires a
+ // country and the tested locale does not have one.
+ public static final int LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER = 3;
+ // The languages and country match, but the variants are different. Or, the reference locale
+ // requires a variant and the tested locale does not have one.
+ public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER = 6;
+ // The required locale is null or empty so it will accept anything, and the tested locale
+ // is non-null and non-empty.
+ public static final int LOCALE_ANY_MATCH = 10;
+ // The language matches, and the tested locale specifies a country but the reference locale
+ // does not require one.
+ public static final int LOCALE_LANGUAGE_MATCH = 15;
+ // The language and the country match, and the tested locale specifies a variant but the
+ // reference locale does not require one.
+ public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH = 20;
+ // The compared locales are fully identical. This is the best match level.
+ public static final int LOCALE_FULL_MATCH = 30;
+
+ // The level at which a match is "normally" considered a locale match with standard algorithms.
+ // Don't use this directly, use #isMatch to test.
+ private static final int LOCALE_MATCH = LOCALE_ANY_MATCH;
+
+ // Make this match the maximum match level. If this evolves to have more than 2 digits
+ // when written in base 10, also adjust the getMatchLevelSortedString method.
+ private static final int MATCH_LEVEL_MAX = 30;
+
+ /**
+ * Return how well a tested locale matches a reference locale.
+ *
+ * This will check the tested locale against the reference locale and return a measure of how
+ * a well it matches the reference. The general idea is that the tested locale has to match
+ * every specified part of the required locale. A full match occur when they are equal, a
+ * partial match when the tested locale agrees with the reference locale but is more specific,
+ * and a difference when the tested locale does not comply with all requirements from the
+ * reference locale.
+ * In more detail, if the reference locale specifies at least a language and the testedLocale
+ * does not specify one, or specifies a different one, LOCALE_NO_MATCH is returned. If the
+ * reference locale is empty or null, it will match anything - in the form of LOCALE_FULL_MATCH
+ * if the tested locale is empty or null, and LOCALE_ANY_MATCH otherwise. If the reference and
+ * tested locale agree on the language, but not on the country,
+ * LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER is returned if the reference locale specifies a country,
+ * and LOCALE_LANGUAGE_MATCH otherwise.
+ * If they agree on both the language and the country, but not on the variant,
+ * LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER is returned if the reference locale
+ * specifies a variant, and LOCALE_LANGUAGE_AND_COUNTRY_MATCH otherwise. If everything matches,
+ * LOCALE_FULL_MATCH is returned.
+ * Examples:
+ * en <=> en_US => LOCALE_LANGUAGE_MATCH
+ * en_US <=> en => LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER
+ * en_US_POSIX <=> en_US_Android => LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER
+ * en_US <=> en_US_Android => LOCALE_LANGUAGE_AND_COUNTRY_MATCH
+ * sp_US <=> en_US => LOCALE_NO_MATCH
+ * de <=> de => LOCALE_FULL_MATCH
+ * en_US <=> en_US => LOCALE_FULL_MATCH
+ * "" <=> en_US => LOCALE_ANY_MATCH
+ *
+ * @param referenceLocale the reference locale to test against.
+ * @param testedLocale the locale to test.
+ * @return a constant that measures how well the tested locale matches the reference locale.
+ */
+ public static int getMatchLevel(final String referenceLocale, final String testedLocale) {
+ if (StringUtils.isEmpty(referenceLocale)) {
+ return StringUtils.isEmpty(testedLocale) ? LOCALE_FULL_MATCH : LOCALE_ANY_MATCH;
+ }
+ if (null == testedLocale) return LOCALE_NO_MATCH;
+ final String[] referenceParams = referenceLocale.split("_", 3);
+ final String[] testedParams = testedLocale.split("_", 3);
+ // By spec of String#split, [0] cannot be null and length cannot be 0.
+ if (!referenceParams[0].equals(testedParams[0])) return LOCALE_NO_MATCH;
+ switch (referenceParams.length) {
+ case 1:
+ return 1 == testedParams.length ? LOCALE_FULL_MATCH : LOCALE_LANGUAGE_MATCH;
+ case 2:
+ if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
+ if (!referenceParams[1].equals(testedParams[1]))
+ return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
+ if (3 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH;
+ return LOCALE_FULL_MATCH;
+ case 3:
+ if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
+ if (!referenceParams[1].equals(testedParams[1]))
+ return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
+ if (2 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER;
+ if (!referenceParams[2].equals(testedParams[2]))
+ return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER;
+ return LOCALE_FULL_MATCH;
+ }
+ // It should be impossible to come here
+ return LOCALE_NO_MATCH;
+ }
+
+ /**
+ * Return a string that represents this match level, with better matches first.
+ *
+ * The strings are sorted in lexicographic order: a better match will always be less than
+ * a worse match when compared together.
+ */
+ public static String getMatchLevelSortedString(final int matchLevel) {
+ // This works because the match levels are 0~99 (actually 0~30)
+ // Ideally this should use a number of digits equals to the 1og10 of the greater matchLevel
+ return String.format(Locale.ROOT, "%02d", MATCH_LEVEL_MAX - matchLevel);
+ }
+
+ /**
+ * Find out whether a match level should be considered a match.
+ *
+ * This method takes a match level as returned by the #getMatchLevel method, and returns whether
+ * it should be considered a match in the usual sense with standard Locale functions.
+ *
+ * @param level the match level, as returned by getMatchLevel.
+ * @return whether this is a match or not.
+ */
+ public static boolean isMatch(final int level) {
+ return LOCALE_MATCH <= level;
+ }
+
+ private static final HashMap<String, Locale> sLocaleCache = new HashMap<>();
+
+ /**
+ * Creates a locale from a string specification.
+ */
+ public static Locale constructLocaleFromString(final String localeStr) {
+ if (localeStr == null)
+ return null;
+ synchronized (sLocaleCache) {
+ if (sLocaleCache.containsKey(localeStr))
+ return sLocaleCache.get(localeStr);
+ Locale retval = null;
+ String[] localeParams = localeStr.split("_", 3);
+ if (localeParams.length == 1) {
+ retval = new Locale(localeParams[0]);
+ } else if (localeParams.length == 2) {
+ retval = new Locale(localeParams[0], localeParams[1]);
+ } else if (localeParams.length == 3) {
+ retval = new Locale(localeParams[0], localeParams[1], localeParams[2]);
+ }
+ if (retval != null) {
+ sLocaleCache.put(localeStr, retval);
+ }
+ return retval;
+ }
+ }
+}