aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java12
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java22
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java395
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java1
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java67
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java209
-rw-r--r--java/src/com/android/inputmethod/latin/Constants.java2
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java6
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java2
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/FormatSpec.java25
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java2
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java10
-rw-r--r--java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java3
-rw-r--r--java/src/com/android/inputmethod/latin/utils/CsvUtils.java7
-rw-r--r--java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java9
17 files changed, 403 insertions, 377 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 5fd70ea63..f7eec6b43 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -284,19 +284,19 @@ public class Key implements Comparable<Key> {
int moreKeysColumn = style.getInt(keyAttr,
R.styleable.Keyboard_Key_maxMoreKeysColumn, params.mMaxMoreKeysKeyboardColumn);
int value;
- if ((value = KeySpecParser.getIntValue(moreKeys, MORE_KEYS_AUTO_COLUMN_ORDER, -1)) > 0) {
+ if ((value = MoreKeySpec.getIntValue(moreKeys, MORE_KEYS_AUTO_COLUMN_ORDER, -1)) > 0) {
moreKeysColumn = value & MORE_KEYS_COLUMN_MASK;
}
- if ((value = KeySpecParser.getIntValue(moreKeys, MORE_KEYS_FIXED_COLUMN_ORDER, -1)) > 0) {
+ if ((value = MoreKeySpec.getIntValue(moreKeys, MORE_KEYS_FIXED_COLUMN_ORDER, -1)) > 0) {
moreKeysColumn = MORE_KEYS_FLAGS_FIXED_COLUMN_ORDER | (value & MORE_KEYS_COLUMN_MASK);
}
- if (KeySpecParser.getBooleanValue(moreKeys, MORE_KEYS_HAS_LABELS)) {
+ if (MoreKeySpec.getBooleanValue(moreKeys, MORE_KEYS_HAS_LABELS)) {
moreKeysColumn |= MORE_KEYS_FLAGS_HAS_LABELS;
}
- if (KeySpecParser.getBooleanValue(moreKeys, MORE_KEYS_NEEDS_DIVIDERS)) {
+ if (MoreKeySpec.getBooleanValue(moreKeys, MORE_KEYS_NEEDS_DIVIDERS)) {
moreKeysColumn |= MORE_KEYS_FLAGS_NEEDS_DIVIDERS;
}
- if (KeySpecParser.getBooleanValue(moreKeys, MORE_KEYS_NO_PANEL_AUTO_MORE_KEY)) {
+ if (MoreKeySpec.getBooleanValue(moreKeys, MORE_KEYS_NO_PANEL_AUTO_MORE_KEY)) {
moreKeysColumn |= MORE_KEYS_FLAGS_NO_PANEL_AUTO_MORE_KEY;
}
mMoreKeysColumnAndFlags = moreKeysColumn;
@@ -308,7 +308,7 @@ public class Key implements Comparable<Key> {
additionalMoreKeys = style.getStringArray(keyAttr,
R.styleable.Keyboard_Key_additionalMoreKeys);
}
- moreKeys = KeySpecParser.insertAdditionalMoreKeys(moreKeys, additionalMoreKeys);
+ moreKeys = MoreKeySpec.insertAdditionalMoreKeys(moreKeys, additionalMoreKeys);
if (moreKeys != null) {
actionFlags |= ACTION_FLAGS_ENABLE_LONG_PRESS;
mMoreKeys = new MoreKeySpec[moreKeys.length];
diff --git a/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java b/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java
index 4ccecb2f0..dce7fc57e 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java
@@ -17,6 +17,7 @@
package com.android.inputmethod.keyboard.internal;
import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.utils.StringUtils;
import android.text.TextUtils;
@@ -29,15 +30,16 @@ import android.text.TextUtils;
* marker. An output text may consist of multiple code points separated by comma.
* The format of the codesArray element should be:
* <pre>
- * codePointInHex[,codePoint2InHex]*(|outputTextCodePointInHex[,outputTextCodePoint2InHex]*)?
+ * label1[,label2]*(|outputText1[,outputText2]*(|minSupportSdkVersion)?)?
* </pre>
*/
// TODO: Write unit tests for this class.
public final class CodesArrayParser {
// Constants for parsing.
- private static final char COMMA = ',';
- private static final String VERTICAL_BAR_STRING = "\\|";
- private static final String COMMA_STRING = ",";
+ private static final char COMMA = Constants.CODE_COMMA;
+ private static final String COMMA_REGEX = StringUtils.newSingleCodePointString(COMMA);
+ private static final String VERTICAL_BAR_REGEX = // "\\|"
+ new String(new char[] { Constants.CODE_BACKSLASH, Constants.CODE_VERTICAL_BAR });
private static final int BASE_HEX = 16;
private CodesArrayParser() {
@@ -45,7 +47,7 @@ public final class CodesArrayParser {
}
private static String getLabelSpec(final String codesArraySpec) {
- final String[] strs = codesArraySpec.split(VERTICAL_BAR_STRING, -1);
+ final String[] strs = codesArraySpec.split(VERTICAL_BAR_REGEX, -1);
if (strs.length <= 1) {
return codesArraySpec;
}
@@ -55,7 +57,7 @@ public final class CodesArrayParser {
public static String parseLabel(final String codesArraySpec) {
final String labelSpec = getLabelSpec(codesArraySpec);
final StringBuilder sb = new StringBuilder();
- for (final String codeInHex : labelSpec.split(COMMA_STRING)) {
+ for (final String codeInHex : labelSpec.split(COMMA_REGEX)) {
final int codePoint = Integer.parseInt(codeInHex, BASE_HEX);
sb.appendCodePoint(codePoint);
}
@@ -63,17 +65,15 @@ public final class CodesArrayParser {
}
private static String getCodeSpec(final String codesArraySpec) {
- final String[] strs = codesArraySpec.split(VERTICAL_BAR_STRING, -1);
+ final String[] strs = codesArraySpec.split(VERTICAL_BAR_REGEX, -1);
if (strs.length <= 1) {
return codesArraySpec;
}
return TextUtils.isEmpty(strs[1]) ? strs[0] : strs[1];
}
- // codesArraySpec consists of:
- // <label>|<code0>,<code1>,...|<minSupportSdkVersion>
public static int getMinSupportSdkVersion(final String codesArraySpec) {
- final String[] strs = codesArraySpec.split(VERTICAL_BAR_STRING, -1);
+ final String[] strs = codesArraySpec.split(VERTICAL_BAR_REGEX, -1);
if (strs.length <= 2) {
return 0;
}
@@ -98,7 +98,7 @@ public final class CodesArrayParser {
return null;
}
final StringBuilder sb = new StringBuilder();
- for (final String codeInHex : codeSpec.split(COMMA_STRING)) {
+ for (final String codeInHex : codeSpec.split(COMMA_REGEX)) {
final int codePoint = Integer.parseInt(codeInHex, BASE_HEX);
sb.appendCodePoint(codePoint);
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
index 5c288c8e7..c51941d32 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
@@ -19,112 +19,47 @@ package com.android.inputmethod.keyboard.internal;
import static com.android.inputmethod.latin.Constants.CODE_OUTPUT_TEXT;
import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED;
-import android.text.TextUtils;
-
-import com.android.inputmethod.latin.LatinImeLogger;
-import com.android.inputmethod.latin.utils.CollectionUtils;
+import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.utils.StringUtils;
-import java.util.ArrayList;
-import java.util.Arrays;
-
/**
- * The string parser of more keys specification.
- * The specification is comma separated texts each of which represents one "more key".
- * The specification might have label or string resource reference in it. These references are
- * expanded before parsing comma.
- * - Label reference should be a string representation of label (!text/label_name)
- * - String resource reference should be a string representation of resource (!text/resource_name)
- * Each "more key" specification is one of the following:
- * - Label optionally followed by keyOutputText or code (keyLabel|keyOutputText).
- * - Icon followed by keyOutputText or code (!icon/icon_name|!code/code_name)
- * - Icon should be a string representation of icon (!icon/icon_name).
- * - Code should be a code point presented by hexadecimal string prefixed with "0x", or a string
- * representation of code (!code/code_name).
+ * The string parser of the key specification.
+ *
+ * Each key specification is one of the following:
+ * - Label optionally followed by keyOutputText (keyLabel|keyOutputText).
+ * - Label optionally followed by code point (keyLabel|!code/code_name).
+ * - Icon followed by keyOutputText (!icon/icon_name|keyOutputText).
+ * - Icon followed by code point (!icon/icon_name|!code/code_name).
+ * Label and keyOutputText are one of the following:
+ * - Literal string.
+ * - Label reference represented by (!text/label_name), see {@link KeyboardTextsSet}.
+ * - String resource reference represented by (!text/resource_name), see {@link KeyboardTextsSet}.
+ * Icon is represented by (!icon/icon_name), see {@link KeyboardIconsSet}.
+ * Code is one of the following:
+ * - Code point presented by hexadecimal string prefixed with "0x"
+ * - Code reference represented by (!code/code_name), see {@link KeyboardCodesSet}.
* Special character, comma ',' backslash '\', and bar '|' can be escaped by '\' character.
- * Note that the '\' is also parsed by XML parser and CSV parser as well.
- * See {@link KeyboardIconsSet} about icon_name.
+ * Note that the '\' is also parsed by XML parser and {@link MoreKeySpec#splitKeySpecs(String)}
+ * as well.
*/
public final class KeySpecParser {
- private static final boolean DEBUG = LatinImeLogger.sDBG;
-
- private static final int MAX_STRING_REFERENCE_INDIRECTION = 10;
-
// Constants for parsing.
- private static final char COMMA = ',';
- private static final char BACKSLASH = '\\';
- private static final char VERTICAL_BAR = '|';
- private static final String PREFIX_TEXT = "!text/";
- static final String PREFIX_ICON = "!icon/";
- private static final String PREFIX_CODE = "!code/";
+ private static final char BACKSLASH = Constants.CODE_BACKSLASH;
+ private static final char VERTICAL_BAR = Constants.CODE_VERTICAL_BAR;
private static final String PREFIX_HEX = "0x";
- private static final String ADDITIONAL_MORE_KEY_MARKER = "%";
private KeySpecParser() {
// Intentional empty constructor for utility class.
}
- /**
- * Split the text containing multiple key specifications separated by commas into an array of
- * key specifications.
- * A key specification can contain a character escaped by the backslash character, including a
- * comma character.
- * Note that an empty key specification will be eliminated from the result array.
- *
- * @param text the text containing multiple key specifications.
- * @return an array of key specification text. Null if the specified <code>text</code> is empty
- * or has no key specifications.
- */
- public static String[] splitKeySpecs(final String text) {
- if (TextUtils.isEmpty(text)) {
- return null;
- }
- final int size = text.length();
- // Optimization for one-letter key specification.
- if (size == 1) {
- return text.charAt(0) == COMMA ? null : new String[] { text };
- }
-
- ArrayList<String> list = null;
- int start = 0;
- // The characters in question in this loop are COMMA and BACKSLASH. These characters never
- // match any high or low surrogate character. So it is OK to iterate through with char
- // index.
- for (int pos = 0; pos < size; pos++) {
- final char c = text.charAt(pos);
- if (c == COMMA) {
- // Skip empty entry.
- if (pos - start > 0) {
- if (list == null) {
- list = CollectionUtils.newArrayList();
- }
- list.add(text.substring(start, pos));
- }
- // Skip comma
- start = pos + 1;
- } else if (c == BACKSLASH) {
- // Skip escape character and escaped character.
- pos++;
- }
- }
- final String remain = (size - start > 0) ? text.substring(start) : null;
- if (list == null) {
- return remain != null ? new String[] { remain } : null;
- }
- if (remain != null) {
- list.add(remain);
- }
- return list.toArray(new String[list.size()]);
- }
-
- private static boolean hasIcon(final String moreKeySpec) {
- return moreKeySpec.startsWith(PREFIX_ICON);
+ private static boolean hasIcon(final String keySpec) {
+ return keySpec.startsWith(KeyboardIconsSet.PREFIX_ICON);
}
- private static boolean hasCode(final String moreKeySpec) {
- final int end = indexOfLabelEnd(moreKeySpec, 0);
- if (end > 0 && end + 1 < moreKeySpec.length() && moreKeySpec.startsWith(
- PREFIX_CODE, end + 1)) {
+ private static boolean hasCode(final String keySpec) {
+ final int end = indexOfLabelEnd(keySpec, 0);
+ if (end > 0 && end + 1 < keySpec.length() && keySpec.startsWith(
+ KeyboardCodesSet.PREFIX_CODE, end + 1)) {
return true;
}
return false;
@@ -149,17 +84,17 @@ public final class KeySpecParser {
return sb.toString();
}
- private static int indexOfLabelEnd(final String moreKeySpec, final int start) {
- if (moreKeySpec.indexOf(BACKSLASH, start) < 0) {
- final int end = moreKeySpec.indexOf(VERTICAL_BAR, start);
+ private static int indexOfLabelEnd(final String keySpec, final int start) {
+ if (keySpec.indexOf(BACKSLASH, start) < 0) {
+ final int end = keySpec.indexOf(VERTICAL_BAR, start);
if (end == 0) {
- throw new KeySpecParserError(VERTICAL_BAR + " at " + start + ": " + moreKeySpec);
+ throw new KeySpecParserError(VERTICAL_BAR + " at " + start + ": " + keySpec);
}
return end;
}
- final int length = moreKeySpec.length();
+ final int length = keySpec.length();
for (int pos = start; pos < length; pos++) {
- final char c = moreKeySpec.charAt(pos);
+ final char c = keySpec.charAt(pos);
if (c == BACKSLASH && pos + 1 < length) {
// Skip escape char
pos++;
@@ -170,63 +105,63 @@ public final class KeySpecParser {
return -1;
}
- public static String getLabel(final String moreKeySpec) {
- if (hasIcon(moreKeySpec)) {
+ public static String getLabel(final String keySpec) {
+ if (hasIcon(keySpec)) {
return null;
}
- final int end = indexOfLabelEnd(moreKeySpec, 0);
- final String label = (end > 0) ? parseEscape(moreKeySpec.substring(0, end))
- : parseEscape(moreKeySpec);
- if (TextUtils.isEmpty(label)) {
- throw new KeySpecParserError("Empty label: " + moreKeySpec);
+ final int end = indexOfLabelEnd(keySpec, 0);
+ final String label = (end > 0) ? parseEscape(keySpec.substring(0, end))
+ : parseEscape(keySpec);
+ if (label.isEmpty()) {
+ throw new KeySpecParserError("Empty label: " + keySpec);
}
return label;
}
- private static String getOutputTextInternal(final String moreKeySpec) {
- final int end = indexOfLabelEnd(moreKeySpec, 0);
+ private static String getOutputTextInternal(final String keySpec) {
+ final int end = indexOfLabelEnd(keySpec, 0);
if (end <= 0) {
return null;
}
- if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0) {
- throw new KeySpecParserError("Multiple " + VERTICAL_BAR + ": " + moreKeySpec);
+ if (indexOfLabelEnd(keySpec, end + 1) >= 0) {
+ throw new KeySpecParserError("Multiple " + VERTICAL_BAR + ": " + keySpec);
}
- return parseEscape(moreKeySpec.substring(end + /* VERTICAL_BAR */1));
+ return parseEscape(keySpec.substring(end + /* VERTICAL_BAR */1));
}
- static String getOutputText(final String moreKeySpec) {
- if (hasCode(moreKeySpec)) {
+ public static String getOutputText(final String keySpec) {
+ if (hasCode(keySpec)) {
return null;
}
- final String outputText = getOutputTextInternal(moreKeySpec);
+ final String outputText = getOutputTextInternal(keySpec);
if (outputText != null) {
if (StringUtils.codePointCount(outputText) == 1) {
// If output text is one code point, it should be treated as a code.
// See {@link #getCode(Resources, String)}.
return null;
}
- if (!TextUtils.isEmpty(outputText)) {
- return outputText;
+ if (outputText.isEmpty()) {
+ throw new KeySpecParserError("Empty outputText: " + keySpec);
}
- throw new KeySpecParserError("Empty outputText: " + moreKeySpec);
+ return outputText;
}
- final String label = getLabel(moreKeySpec);
+ final String label = getLabel(keySpec);
if (label == null) {
- throw new KeySpecParserError("Empty label: " + moreKeySpec);
+ throw new KeySpecParserError("Empty label: " + keySpec);
}
// Code is automatically generated for one letter label. See {@link getCode()}.
return (StringUtils.codePointCount(label) == 1) ? null : label;
}
- static int getCode(final String moreKeySpec, final KeyboardCodesSet codesSet) {
- if (hasCode(moreKeySpec)) {
- final int end = indexOfLabelEnd(moreKeySpec, 0);
- if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0) {
- throw new KeySpecParserError("Multiple " + VERTICAL_BAR + ": " + moreKeySpec);
+ public static int getCode(final String keySpec, final KeyboardCodesSet codesSet) {
+ if (hasCode(keySpec)) {
+ final int end = indexOfLabelEnd(keySpec, 0);
+ if (indexOfLabelEnd(keySpec, end + 1) >= 0) {
+ throw new KeySpecParserError("Multiple " + VERTICAL_BAR + ": " + keySpec);
}
- return parseCode(moreKeySpec.substring(end + 1), codesSet, CODE_UNSPECIFIED);
+ return parseCode(keySpec.substring(end + 1), codesSet, CODE_UNSPECIFIED);
}
- final String outputText = getOutputTextInternal(moreKeySpec);
+ final String outputText = getOutputTextInternal(keySpec);
if (outputText != null) {
// If output text is one code point, it should be treated as a code.
// See {@link #getOutputText(String)}.
@@ -235,7 +170,7 @@ public final class KeySpecParser {
}
return CODE_OUTPUT_TEXT;
}
- final String label = getLabel(moreKeySpec);
+ final String label = getLabel(keySpec);
// Code is automatically generated for one letter label.
if (StringUtils.codePointCount(label) == 1) {
return label.codePointAt(0);
@@ -246,8 +181,8 @@ public final class KeySpecParser {
public static int parseCode(final String text, final KeyboardCodesSet codesSet,
final int defCode) {
if (text == null) return defCode;
- if (text.startsWith(PREFIX_CODE)) {
- return codesSet.getCode(text.substring(PREFIX_CODE.length()));
+ if (text.startsWith(KeyboardCodesSet.PREFIX_CODE)) {
+ return codesSet.getCode(text.substring(KeyboardCodesSet.PREFIX_CODE.length()));
} else if (text.startsWith(PREFIX_HEX)) {
return Integer.parseInt(text.substring(PREFIX_HEX.length()), 16);
} else {
@@ -255,214 +190,22 @@ public final class KeySpecParser {
}
}
- public static int getIconId(final String moreKeySpec) {
- if (moreKeySpec != null && hasIcon(moreKeySpec)) {
- final int end = moreKeySpec.indexOf(VERTICAL_BAR, PREFIX_ICON.length());
- final String name = (end < 0) ? moreKeySpec.substring(PREFIX_ICON.length())
- : moreKeySpec.substring(PREFIX_ICON.length(), end);
+ public static int getIconId(final String keySpec) {
+ if (keySpec != null && hasIcon(keySpec)) {
+ final int end = keySpec.indexOf(
+ VERTICAL_BAR, KeyboardIconsSet.PREFIX_ICON.length());
+ final String name = (end < 0)
+ ? keySpec.substring(KeyboardIconsSet.PREFIX_ICON.length())
+ : keySpec.substring(KeyboardIconsSet.PREFIX_ICON.length(), end);
return KeyboardIconsSet.getIconId(name);
}
return KeyboardIconsSet.ICON_UNDEFINED;
}
- private static final String[] EMPTY_STRING_ARRAY = new String[0];
-
- private static String[] filterOutEmptyString(final String[] array) {
- if (array == null) {
- return EMPTY_STRING_ARRAY;
- }
- ArrayList<String> out = null;
- for (int i = 0; i < array.length; i++) {
- final String entry = array[i];
- if (TextUtils.isEmpty(entry)) {
- if (out == null) {
- out = CollectionUtils.arrayAsList(array, 0, i);
- }
- } else if (out != null) {
- out.add(entry);
- }
- }
- if (out == null) {
- return array;
- }
- return out.toArray(new String[out.size()]);
- }
-
- public static String[] insertAdditionalMoreKeys(final String[] moreKeySpecs,
- final String[] additionalMoreKeySpecs) {
- final String[] moreKeys = filterOutEmptyString(moreKeySpecs);
- final String[] additionalMoreKeys = filterOutEmptyString(additionalMoreKeySpecs);
- final int moreKeysCount = moreKeys.length;
- final int additionalCount = additionalMoreKeys.length;
- ArrayList<String> out = null;
- int additionalIndex = 0;
- for (int moreKeyIndex = 0; moreKeyIndex < moreKeysCount; moreKeyIndex++) {
- final String moreKeySpec = moreKeys[moreKeyIndex];
- if (moreKeySpec.equals(ADDITIONAL_MORE_KEY_MARKER)) {
- if (additionalIndex < additionalCount) {
- // Replace '%' marker with additional more key specification.
- final String additionalMoreKey = additionalMoreKeys[additionalIndex];
- if (out != null) {
- out.add(additionalMoreKey);
- } else {
- moreKeys[moreKeyIndex] = additionalMoreKey;
- }
- additionalIndex++;
- } else {
- // Filter out excessive '%' marker.
- if (out == null) {
- out = CollectionUtils.arrayAsList(moreKeys, 0, moreKeyIndex);
- }
- }
- } else {
- if (out != null) {
- out.add(moreKeySpec);
- }
- }
- }
- if (additionalCount > 0 && additionalIndex == 0) {
- // No '%' marker is found in more keys.
- // Insert all additional more keys to the head of more keys.
- if (DEBUG && out != null) {
- throw new RuntimeException("Internal logic error:"
- + " moreKeys=" + Arrays.toString(moreKeys)
- + " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys));
- }
- out = CollectionUtils.arrayAsList(additionalMoreKeys, additionalIndex, additionalCount);
- for (int i = 0; i < moreKeysCount; i++) {
- out.add(moreKeys[i]);
- }
- } else if (additionalIndex < additionalCount) {
- // The number of '%' markers are less than additional more keys.
- // Append remained additional more keys to the tail of more keys.
- if (DEBUG && out != null) {
- throw new RuntimeException("Internal logic error:"
- + " moreKeys=" + Arrays.toString(moreKeys)
- + " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys));
- }
- out = CollectionUtils.arrayAsList(moreKeys, 0, moreKeysCount);
- for (int i = additionalIndex; i < additionalCount; i++) {
- out.add(additionalMoreKeys[additionalIndex]);
- }
- }
- if (out == null && moreKeysCount > 0) {
- return moreKeys;
- } else if (out != null && out.size() > 0) {
- return out.toArray(new String[out.size()]);
- } else {
- return null;
- }
- }
-
@SuppressWarnings("serial")
public static final class KeySpecParserError extends RuntimeException {
public KeySpecParserError(final String message) {
super(message);
}
}
-
- public static String resolveTextReference(final String rawText,
- final KeyboardTextsSet textsSet) {
- if (TextUtils.isEmpty(rawText)) {
- return null;
- }
- int level = 0;
- String text = rawText;
- StringBuilder sb;
- do {
- level++;
- if (level >= MAX_STRING_REFERENCE_INDIRECTION) {
- throw new RuntimeException("too many @string/resource indirection: " + text);
- }
-
- final int prefixLen = PREFIX_TEXT.length();
- final int size = text.length();
- if (size < prefixLen) {
- return TextUtils.isEmpty(text) ? null : text;
- }
-
- sb = null;
- for (int pos = 0; pos < size; pos++) {
- final char c = text.charAt(pos);
- if (text.startsWith(PREFIX_TEXT, pos) && textsSet != null) {
- if (sb == null) {
- sb = new StringBuilder(text.substring(0, pos));
- }
- final int end = searchTextNameEnd(text, pos + prefixLen);
- final String name = text.substring(pos + prefixLen, end);
- sb.append(textsSet.getText(name));
- pos = end - 1;
- } else if (c == BACKSLASH) {
- if (sb != null) {
- // Append both escape character and escaped character.
- sb.append(text.substring(pos, Math.min(pos + 2, size)));
- }
- pos++;
- } else if (sb != null) {
- sb.append(c);
- }
- }
-
- if (sb != null) {
- text = sb.toString();
- }
- } while (sb != null);
- return TextUtils.isEmpty(text) ? null : text;
- }
-
- private static int searchTextNameEnd(final String text, final int start) {
- final int size = text.length();
- for (int pos = start; pos < size; pos++) {
- final char c = text.charAt(pos);
- // Label name should be consisted of [a-zA-Z_0-9].
- if ((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')) {
- continue;
- }
- return pos;
- }
- return size;
- }
-
- public static int getIntValue(final String[] moreKeys, final String key,
- final int defaultValue) {
- if (moreKeys == null) {
- return defaultValue;
- }
- final int keyLen = key.length();
- boolean foundValue = false;
- int value = defaultValue;
- for (int i = 0; i < moreKeys.length; i++) {
- final String moreKeySpec = moreKeys[i];
- if (moreKeySpec == null || !moreKeySpec.startsWith(key)) {
- continue;
- }
- moreKeys[i] = null;
- try {
- if (!foundValue) {
- value = Integer.parseInt(moreKeySpec.substring(keyLen));
- foundValue = true;
- }
- } catch (NumberFormatException e) {
- throw new RuntimeException(
- "integer should follow after " + key + ": " + moreKeySpec);
- }
- }
- return value;
- }
-
- public static boolean getBooleanValue(final String[] moreKeys, final String key) {
- if (moreKeys == null) {
- return false;
- }
- boolean value = false;
- for (int i = 0; i < moreKeys.length; i++) {
- final String moreKeySpec = moreKeys[i];
- if (moreKeySpec == null || !moreKeySpec.equals(key)) {
- continue;
- }
- moreKeys[i] = null;
- value = true;
- }
- return value;
- }
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java
index e6a674334..7941ddd41 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java
@@ -32,15 +32,15 @@ public abstract class KeyStyle {
protected String parseString(final TypedArray a, final int index) {
if (a.hasValue(index)) {
- return KeySpecParser.resolveTextReference(a.getString(index), mTextsSet);
+ return mTextsSet.resolveTextReference(a.getString(index));
}
return null;
}
protected String[] parseStringArray(final TypedArray a, final int index) {
if (a.hasValue(index)) {
- final String text = KeySpecParser.resolveTextReference(a.getString(index), mTextsSet);
- return KeySpecParser.splitKeySpecs(text);
+ final String text = mTextsSet.resolveTextReference(a.getString(index));
+ return MoreKeySpec.splitKeySpecs(text);
}
return null;
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
index 78809d53b..aeb4db557 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
@@ -22,6 +22,8 @@ import com.android.inputmethod.latin.utils.CollectionUtils;
import java.util.HashMap;
public final class KeyboardCodesSet {
+ public static final String PREFIX_CODE = "!code/";
+
private static final HashMap<String, int[]> sLanguageToCodesMap = CollectionUtils.newHashMap();
private static final HashMap<String, Integer> sNameToIdMap = CollectionUtils.newHashMap();
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index 0ee935f60..da8bf7d69 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -30,6 +30,7 @@ import java.util.HashMap;
public final class KeyboardIconsSet {
private static final String TAG = KeyboardIconsSet.class.getSimpleName();
+ public static final String PREFIX_ICON = "!icon/";
public static final int ICON_UNDEFINED = 0;
private static final int ATTR_UNDEFINED = 0;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
index 4e8eb3ea7..f8c098893 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
@@ -18,8 +18,10 @@ package com.android.inputmethod.keyboard.internal;
import android.content.Context;
import android.content.res.Resources;
+import android.text.TextUtils;
import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.utils.CollectionUtils;
import java.util.HashMap;
@@ -45,6 +47,10 @@ import java.util.HashMap;
* KeyboardTextsSet.java
*/
public final class KeyboardTextsSet {
+ public static final String PREFIX_TEXT = "!text/";
+ private static final char BACKSLASH = Constants.CODE_BACKSLASH;
+ private static final int MAX_STRING_REFERENCE_INDIRECTION = 10;
+
// Language to texts map.
private static final HashMap<String, String[]> sLocaleToTextsMap = CollectionUtils.newHashMap();
private static final HashMap<String, Integer> sNameToIdsMap = CollectionUtils.newHashMap();
@@ -87,6 +93,67 @@ public final class KeyboardTextsSet {
return (text == null) ? LANGUAGE_DEFAULT[id] : text;
}
+ private static int searchTextNameEnd(final String text, final int start) {
+ final int size = text.length();
+ for (int pos = start; pos < size; pos++) {
+ final char c = text.charAt(pos);
+ // Label name should be consisted of [a-zA-Z_0-9].
+ if ((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')) {
+ continue;
+ }
+ return pos;
+ }
+ return size;
+ }
+
+ public String resolveTextReference(final String rawText) {
+ if (TextUtils.isEmpty(rawText)) {
+ return null;
+ }
+ int level = 0;
+ String text = rawText;
+ StringBuilder sb;
+ do {
+ level++;
+ if (level >= MAX_STRING_REFERENCE_INDIRECTION) {
+ throw new RuntimeException("too many @string/resource indirection: " + text);
+ }
+
+ final int prefixLen = PREFIX_TEXT.length();
+ final int size = text.length();
+ if (size < prefixLen) {
+ return TextUtils.isEmpty(text) ? null : text;
+ }
+
+ sb = null;
+ for (int pos = 0; pos < size; pos++) {
+ final char c = text.charAt(pos);
+ if (text.startsWith(PREFIX_TEXT, pos)) {
+ if (sb == null) {
+ sb = new StringBuilder(text.substring(0, pos));
+ }
+ final int end = searchTextNameEnd(text, pos + prefixLen);
+ final String name = text.substring(pos + prefixLen, end);
+ sb.append(getText(name));
+ pos = end - 1;
+ } else if (c == BACKSLASH) {
+ if (sb != null) {
+ // Append both escape character and escaped character.
+ sb.append(text.substring(pos, Math.min(pos + 2, size)));
+ }
+ pos++;
+ } else if (sb != null) {
+ sb.append(c);
+ }
+ }
+
+ if (sb != null) {
+ text = sb.toString();
+ }
+ } while (sb != null);
+ return TextUtils.isEmpty(text) ? null : text;
+ }
+
// These texts' name should be aligned with the @string/<name> in
// values*/strings-action-keys.xml.
private static final String[] RESOURCE_NAMES = {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java
index 889fc9c7e..d3bc0c2b2 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java
@@ -19,10 +19,25 @@ package com.android.inputmethod.keyboard.internal;
import android.text.TextUtils;
import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.LatinImeLogger;
+import com.android.inputmethod.latin.utils.CollectionUtils;
import com.android.inputmethod.latin.utils.StringUtils;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Locale;
+/**
+ * The more key specification object. The more keys are an array of {@link MoreKeySpec}.
+ *
+ * The more keys specification is comma separated "key specification" each of which represents one
+ * "more key".
+ * The key specification might have label or string resource reference in it. These references are
+ * expanded before parsing comma.
+ * Special character, comma ',' backslash '\' can be escaped by '\' character.
+ * Note that the '\' is also parsed by XML parser and {@link MoreKeySpec#splitKeySpecs(String)}
+ * as well.
+ */
public final class MoreKeySpec {
public final int mCode;
public final String mLabel;
@@ -74,7 +89,7 @@ public final class MoreKeySpec {
@Override
public String toString() {
final String label = (mIconId == KeyboardIconsSet.ICON_UNDEFINED ? mLabel
- : KeySpecParser.PREFIX_ICON + KeyboardIconsSet.getIconName(mIconId));
+ : KeyboardIconsSet.PREFIX_ICON + KeyboardIconsSet.getIconName(mIconId));
final String output = (mCode == Constants.CODE_OUTPUT_TEXT ? mOutputText
: Constants.printableCode(mCode));
if (StringUtils.codePointCount(label) == 1 && label.codePointAt(0) == mCode) {
@@ -83,4 +98,196 @@ public final class MoreKeySpec {
return label + "|" + output;
}
}
+
+ private static final boolean DEBUG = LatinImeLogger.sDBG;
+ // Constants for parsing.
+ private static final char COMMA = Constants.CODE_COMMA;
+ private static final char BACKSLASH = Constants.CODE_BACKSLASH;
+ private static final String ADDITIONAL_MORE_KEY_MARKER =
+ StringUtils.newSingleCodePointString(Constants.CODE_PERCENT);
+
+ /**
+ * Split the text containing multiple key specifications separated by commas into an array of
+ * key specifications.
+ * A key specification can contain a character escaped by the backslash character, including a
+ * comma character.
+ * Note that an empty key specification will be eliminated from the result array.
+ *
+ * @param text the text containing multiple key specifications.
+ * @return an array of key specification text. Null if the specified <code>text</code> is empty
+ * or has no key specifications.
+ */
+ public static String[] splitKeySpecs(final String text) {
+ if (TextUtils.isEmpty(text)) {
+ return null;
+ }
+ final int size = text.length();
+ // Optimization for one-letter key specification.
+ if (size == 1) {
+ return text.charAt(0) == COMMA ? null : new String[] { text };
+ }
+
+ ArrayList<String> list = null;
+ int start = 0;
+ // The characters in question in this loop are COMMA and BACKSLASH. These characters never
+ // match any high or low surrogate character. So it is OK to iterate through with char
+ // index.
+ for (int pos = 0; pos < size; pos++) {
+ final char c = text.charAt(pos);
+ if (c == COMMA) {
+ // Skip empty entry.
+ if (pos - start > 0) {
+ if (list == null) {
+ list = CollectionUtils.newArrayList();
+ }
+ list.add(text.substring(start, pos));
+ }
+ // Skip comma
+ start = pos + 1;
+ } else if (c == BACKSLASH) {
+ // Skip escape character and escaped character.
+ pos++;
+ }
+ }
+ final String remain = (size - start > 0) ? text.substring(start) : null;
+ if (list == null) {
+ return remain != null ? new String[] { remain } : null;
+ }
+ if (remain != null) {
+ list.add(remain);
+ }
+ return list.toArray(new String[list.size()]);
+ }
+
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+ private static String[] filterOutEmptyString(final String[] array) {
+ if (array == null) {
+ return EMPTY_STRING_ARRAY;
+ }
+ ArrayList<String> out = null;
+ for (int i = 0; i < array.length; i++) {
+ final String entry = array[i];
+ if (TextUtils.isEmpty(entry)) {
+ if (out == null) {
+ out = CollectionUtils.arrayAsList(array, 0, i);
+ }
+ } else if (out != null) {
+ out.add(entry);
+ }
+ }
+ if (out == null) {
+ return array;
+ }
+ return out.toArray(new String[out.size()]);
+ }
+
+ public static String[] insertAdditionalMoreKeys(final String[] moreKeySpecs,
+ final String[] additionalMoreKeySpecs) {
+ final String[] moreKeys = filterOutEmptyString(moreKeySpecs);
+ final String[] additionalMoreKeys = filterOutEmptyString(additionalMoreKeySpecs);
+ final int moreKeysCount = moreKeys.length;
+ final int additionalCount = additionalMoreKeys.length;
+ ArrayList<String> out = null;
+ int additionalIndex = 0;
+ for (int moreKeyIndex = 0; moreKeyIndex < moreKeysCount; moreKeyIndex++) {
+ final String moreKeySpec = moreKeys[moreKeyIndex];
+ if (moreKeySpec.equals(ADDITIONAL_MORE_KEY_MARKER)) {
+ if (additionalIndex < additionalCount) {
+ // Replace '%' marker with additional more key specification.
+ final String additionalMoreKey = additionalMoreKeys[additionalIndex];
+ if (out != null) {
+ out.add(additionalMoreKey);
+ } else {
+ moreKeys[moreKeyIndex] = additionalMoreKey;
+ }
+ additionalIndex++;
+ } else {
+ // Filter out excessive '%' marker.
+ if (out == null) {
+ out = CollectionUtils.arrayAsList(moreKeys, 0, moreKeyIndex);
+ }
+ }
+ } else {
+ if (out != null) {
+ out.add(moreKeySpec);
+ }
+ }
+ }
+ if (additionalCount > 0 && additionalIndex == 0) {
+ // No '%' marker is found in more keys.
+ // Insert all additional more keys to the head of more keys.
+ if (DEBUG && out != null) {
+ throw new RuntimeException("Internal logic error:"
+ + " moreKeys=" + Arrays.toString(moreKeys)
+ + " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys));
+ }
+ out = CollectionUtils.arrayAsList(additionalMoreKeys, additionalIndex, additionalCount);
+ for (int i = 0; i < moreKeysCount; i++) {
+ out.add(moreKeys[i]);
+ }
+ } else if (additionalIndex < additionalCount) {
+ // The number of '%' markers are less than additional more keys.
+ // Append remained additional more keys to the tail of more keys.
+ if (DEBUG && out != null) {
+ throw new RuntimeException("Internal logic error:"
+ + " moreKeys=" + Arrays.toString(moreKeys)
+ + " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys));
+ }
+ out = CollectionUtils.arrayAsList(moreKeys, 0, moreKeysCount);
+ for (int i = additionalIndex; i < additionalCount; i++) {
+ out.add(additionalMoreKeys[additionalIndex]);
+ }
+ }
+ if (out == null && moreKeysCount > 0) {
+ return moreKeys;
+ } else if (out != null && out.size() > 0) {
+ return out.toArray(new String[out.size()]);
+ } else {
+ return null;
+ }
+ }
+
+ public static int getIntValue(final String[] moreKeys, final String key,
+ final int defaultValue) {
+ if (moreKeys == null) {
+ return defaultValue;
+ }
+ final int keyLen = key.length();
+ boolean foundValue = false;
+ int value = defaultValue;
+ for (int i = 0; i < moreKeys.length; i++) {
+ final String moreKeySpec = moreKeys[i];
+ if (moreKeySpec == null || !moreKeySpec.startsWith(key)) {
+ continue;
+ }
+ moreKeys[i] = null;
+ try {
+ if (!foundValue) {
+ value = Integer.parseInt(moreKeySpec.substring(keyLen));
+ foundValue = true;
+ }
+ } catch (NumberFormatException e) {
+ throw new RuntimeException(
+ "integer should follow after " + key + ": " + moreKeySpec);
+ }
+ }
+ return value;
+ }
+
+ public static boolean getBooleanValue(final String[] moreKeys, final String key) {
+ if (moreKeys == null) {
+ return false;
+ }
+ boolean value = false;
+ for (int i = 0; i < moreKeys.length; i++) {
+ final String moreKeySpec = moreKeys[i];
+ if (moreKeySpec == null || !moreKeySpec.equals(key)) {
+ continue;
+ }
+ moreKeys[i] = null;
+ value = true;
+ }
+ return value;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
index 0b396b1de..d6ac71fe2 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -191,6 +191,8 @@ public final class Constants {
public static final int CODE_QUESTION_MARK = '?';
public static final int CODE_EXCLAMATION_MARK = '!';
public static final int CODE_SLASH = '/';
+ public static final int CODE_BACKSLASH = '\\';
+ public static final int CODE_VERTICAL_BAR = '|';
public static final int CODE_COMMERCIAL_AT = '@';
public static final int CODE_PLUS = '+';
public static final int CODE_PERCENT = '%';
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 8e1675b2a..4dee84a7b 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -267,9 +267,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
protected Map<String, String> getHeaderAttributeMap() {
HashMap<String, String> attributeMap = new HashMap<String, String>();
- attributeMap.put(FormatSpec.FileHeader.DICTIONARY_ID_ATTRIBUTE, mDictName);
- attributeMap.put(FormatSpec.FileHeader.DICTIONARY_LOCALE_ATTRIBUTE, mLocale.toString());
- attributeMap.put(FormatSpec.FileHeader.DICTIONARY_VERSION_ATTRIBUTE,
+ attributeMap.put(FormatSpec.FileHeader.DICTIONARY_ID_KEY, mDictName);
+ attributeMap.put(FormatSpec.FileHeader.DICTIONARY_LOCALE_KEY, mLocale.toString());
+ attributeMap.put(FormatSpec.FileHeader.DICTIONARY_VERSION_KEY,
String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())));
return attributeMap;
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java
index 370782b33..1a9118147 100644
--- a/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java
@@ -60,7 +60,7 @@ public abstract class AbstractDictDecoder implements DictDecoder {
final FileHeader header = new FileHeader(headerSize,
new FusionDictionary.DictionaryOptions(attributes),
new FormatOptions(version, FileHeader.ATTRIBUTE_VALUE_TRUE.equals(
- attributes.get(FileHeader.HAS_HISTORICAL_INFO_ATTRIBUTE))));
+ attributes.get(FileHeader.HAS_HISTORICAL_INFO_KEY))));
return header;
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
index 61c17fc46..74e305976 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
@@ -336,16 +336,19 @@ public final class FormatSpec {
public final int mBodyOffset;
public final DictionaryOptions mDictionaryOptions;
public final FormatOptions mFormatOptions;
+
// Note that these are corresponding definitions in native code in latinime::HeaderPolicy
// and latinime::HeaderReadWriteUtils.
- public static final String USES_FORGETTING_CURVE_ATTRIBUTE = "USES_FORGETTING_CURVE";
- public static final String HAS_HISTORICAL_INFO_ATTRIBUTE = "HAS_HISTORICAL_INFO";
+ // TODO: Standardize the key names and bump up the format version, taking care not to
+ // break format version 2 dictionaries.
+ public static final String DICTIONARY_VERSION_KEY = "version";
+ public static final String DICTIONARY_LOCALE_KEY = "locale";
+ public static final String DICTIONARY_ID_KEY = "dictionary";
+ public static final String DICTIONARY_DESCRIPTION_KEY = "description";
+ public static final String DICTIONARY_DATE_KEY = "date";
+ public static final String HAS_HISTORICAL_INFO_KEY = "HAS_HISTORICAL_INFO";
+ public static final String USES_FORGETTING_CURVE_KEY = "USES_FORGETTING_CURVE";
public static final String ATTRIBUTE_VALUE_TRUE = "1";
-
- public static final String DICTIONARY_VERSION_ATTRIBUTE = "version";
- public static final String DICTIONARY_LOCALE_ATTRIBUTE = "locale";
- public static final String DICTIONARY_ID_ATTRIBUTE = "dictionary";
- private static final String DICTIONARY_DESCRIPTION_ATTRIBUTE = "description";
public FileHeader(final int headerSize, final DictionaryOptions dictionaryOptions,
final FormatOptions formatOptions) throws UnsupportedFormatException {
mDictionaryOptions = dictionaryOptions;
@@ -365,24 +368,24 @@ public final class FormatSpec {
// Helper method to get the locale as a String
public String getLocaleString() {
- return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_LOCALE_ATTRIBUTE);
+ return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_LOCALE_KEY);
}
// Helper method to get the version String
public String getVersion() {
- return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_VERSION_ATTRIBUTE);
+ return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_VERSION_KEY);
}
// Helper method to get the dictionary ID as a String
public String getId() {
- return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_ID_ATTRIBUTE);
+ return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_ID_KEY);
}
// Helper method to get the description
public String getDescription() {
// TODO: Right now each dictionary file comes with a description in its own language.
// It will display as is no matter the device's locale. It should be internationalized.
- return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_DESCRIPTION_ATTRIBUTE);
+ return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_DESCRIPTION_KEY);
}
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
index d34aa171e..b12f79b07 100644
--- a/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
@@ -62,7 +62,7 @@ public class Ver4DictEncoder implements DictEncoder {
final BinaryDictionary binaryDict = new BinaryDictionary(mDictPlacedDir.getAbsolutePath(),
0l, mDictPlacedDir.length(), true /* useFullEditDistance */,
LocaleUtils.constructLocaleFromString(dict.mOptions.mAttributes.get(
- FormatSpec.FileHeader.DICTIONARY_LOCALE_ATTRIBUTE)),
+ FormatSpec.FileHeader.DICTIONARY_LOCALE_KEY)),
Dictionary.TYPE_USER /* Dictionary type. Does not matter for us */,
true /* isUpdatable */);
if (!binaryDict.isValidDictionary()) {
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
index 4a610e6f9..d636a253a 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
@@ -95,13 +95,13 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
@Override
protected Map<String, String> getHeaderAttributeMap() {
HashMap<String, String> attributeMap = new HashMap<String, String>();
- attributeMap.put(FormatSpec.FileHeader.USES_FORGETTING_CURVE_ATTRIBUTE,
+ attributeMap.put(FormatSpec.FileHeader.USES_FORGETTING_CURVE_KEY,
FormatSpec.FileHeader.ATTRIBUTE_VALUE_TRUE);
- attributeMap.put(FormatSpec.FileHeader.HAS_HISTORICAL_INFO_ATTRIBUTE,
+ attributeMap.put(FormatSpec.FileHeader.HAS_HISTORICAL_INFO_KEY,
FormatSpec.FileHeader.ATTRIBUTE_VALUE_TRUE);
- attributeMap.put(FormatSpec.FileHeader.DICTIONARY_ID_ATTRIBUTE, mDictName);
- attributeMap.put(FormatSpec.FileHeader.DICTIONARY_LOCALE_ATTRIBUTE, mLocale.toString());
- attributeMap.put(FormatSpec.FileHeader.DICTIONARY_VERSION_ATTRIBUTE,
+ attributeMap.put(FormatSpec.FileHeader.DICTIONARY_ID_KEY, mDictName);
+ attributeMap.put(FormatSpec.FileHeader.DICTIONARY_LOCALE_KEY, mLocale.toString());
+ attributeMap.put(FormatSpec.FileHeader.DICTIONARY_VERSION_KEY,
String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())));
return attributeMap;
}
diff --git a/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java b/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
index 8ba32ff76..70cb2b285 100644
--- a/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
+++ b/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
@@ -19,6 +19,7 @@ package com.android.inputmethod.latin.settings;
import android.content.res.Resources;
import com.android.inputmethod.keyboard.internal.KeySpecParser;
+import com.android.inputmethod.keyboard.internal.MoreKeySpec;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.R;
@@ -55,7 +56,7 @@ public final class SpacingAndPunctuations {
res.getString(R.string.symbols_word_connectors));
mSortedWordSeparators = StringUtils.toSortedCodePointArray(
res.getString(R.string.symbols_word_separators));
- final String[] suggestPuncsSpec = KeySpecParser.splitKeySpecs(res.getString(
+ final String[] suggestPuncsSpec = MoreKeySpec.splitKeySpecs(res.getString(
R.string.suggested_punctuations));
mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec);
mSentenceSeparator = res.getInteger(R.integer.sentence_separator);
diff --git a/java/src/com/android/inputmethod/latin/utils/CsvUtils.java b/java/src/com/android/inputmethod/latin/utils/CsvUtils.java
index 36b927eea..b18a1d83b 100644
--- a/java/src/com/android/inputmethod/latin/utils/CsvUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CsvUtils.java
@@ -17,6 +17,7 @@
package com.android.inputmethod.latin.utils;
import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.latin.Constants;
import java.util.ArrayList;
@@ -57,9 +58,9 @@ public final class CsvUtils {
// Note that none of these characters match high or low surrogate characters, so we need not
// take care of matching by code point.
- private static final char COMMA = ',';
- private static final char SPACE = ' ';
- private static final char QUOTE = '"';
+ private static final char COMMA = Constants.CODE_COMMA;
+ private static final char SPACE = Constants.CODE_SPACE;
+ private static final char QUOTE = Constants.CODE_DOUBLE_QUOTE;
@SuppressWarnings("serial")
public static class CsvParseException extends RuntimeException {
diff --git a/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java
index a6ae640d3..7af03da59 100644
--- a/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java
@@ -22,6 +22,7 @@ import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.makedict.BinaryDictIOUtils;
import com.android.inputmethod.latin.makedict.DictDecoder;
import com.android.inputmethod.latin.makedict.DictEncoder;
+import com.android.inputmethod.latin.makedict.FormatSpec;
import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
import com.android.inputmethod.latin.makedict.FusionDictionary;
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
@@ -44,9 +45,6 @@ import java.util.concurrent.TimeUnit;
public final class UserHistoryDictIOUtils {
private static final String TAG = UserHistoryDictIOUtils.class.getSimpleName();
private static final boolean DEBUG = false;
- private static final String USES_FORGETTING_CURVE_KEY = "USES_FORGETTING_CURVE";
- private static final String USES_FORGETTING_CURVE_VALUE = "1";
- private static final String DATE_KEY = "date";
public interface OnAddWordListener {
/**
@@ -75,8 +73,9 @@ public final class UserHistoryDictIOUtils {
final BigramDictionaryInterface dict, final UserHistoryDictionaryBigramList bigrams,
final FormatOptions formatOptions, final HashMap<String, String> options) {
final FusionDictionary fusionDict = constructFusionDictionary(dict, bigrams, options);
- fusionDict.addOptionAttribute(USES_FORGETTING_CURVE_KEY, USES_FORGETTING_CURVE_VALUE);
- fusionDict.addOptionAttribute(DATE_KEY,
+ fusionDict.addOptionAttribute(FormatSpec.FileHeader.USES_FORGETTING_CURVE_KEY,
+ FormatSpec.FileHeader.ATTRIBUTE_VALUE_TRUE);
+ fusionDict.addOptionAttribute(FormatSpec.FileHeader.DICTIONARY_DATE_KEY,
String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())));
try {
dictEncoder.writeDictionary(fusionDict, formatOptions);