aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/res/values/strings-config-important-notice.xml24
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java106
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java4
-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.java66
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.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/utils/CollectionUtils.java15
-rw-r--r--java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java14
-rw-r--r--java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java9
-rw-r--r--native/jni/src/suggest/core/dictionary/word_property.cpp9
-rw-r--r--native/jni/src/suggest/core/dictionary/word_property.h50
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp10
-rw-r--r--tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserSplitTests.java8
-rw-r--r--tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java2
-rw-r--r--tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java10
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java10
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtilsTests.java6
-rw-r--r--tools/dicttool/Android.mk2
-rw-r--r--tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java12
-rw-r--r--tools/make-keyboard-text/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl66
26 files changed, 300 insertions, 173 deletions
diff --git a/java/res/values/strings-config-important-notice.xml b/java/res/values/strings-config-important-notice.xml
new file mode 100644
index 000000000..8ee0b99c3
--- /dev/null
+++ b/java/res/values/strings-config-important-notice.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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.
+*/
+-->
+
+<resources>
+ <integer name="config_important_notice_version">0</integer>
+ <!-- TODO: Add important notice title and description string resources. -->
+</resources>
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
index e9e2f4254..07c5cae8a 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
@@ -48,15 +48,10 @@ import java.util.Arrays;
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 String PREFIX_HEX = "0x";
private static final String ADDITIONAL_MORE_KEY_MARKER = "%";
@@ -118,13 +113,13 @@ public final class KeySpecParser {
}
private static boolean hasIcon(final String moreKeySpec) {
- return moreKeySpec.startsWith(PREFIX_ICON);
+ return moreKeySpec.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)) {
+ KeyboardCodesSet.PREFIX_CODE, end + 1)) {
return true;
}
return false;
@@ -246,8 +241,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 {
@@ -257,29 +252,16 @@ 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);
+ final int end = moreKeySpec.indexOf(
+ VERTICAL_BAR, KeyboardIconsSet.PREFIX_ICON.length());
+ final String name = (end < 0)
+ ? moreKeySpec.substring(KeyboardIconsSet.PREFIX_ICON.length())
+ : moreKeySpec.substring(KeyboardIconsSet.PREFIX_ICON.length(), end);
return KeyboardIconsSet.getIconId(name);
}
return KeyboardIconsSet.ICON_UNDEFINED;
}
- private static <T> ArrayList<T> arrayAsList(final T[] array, final int start, final int end) {
- if (array == null) {
- throw new NullPointerException();
- }
- if (start < 0 || start > end || end > array.length) {
- throw new IllegalArgumentException();
- }
-
- final ArrayList<T> list = CollectionUtils.newArrayList(end - start);
- for (int i = start; i < end; i++) {
- list.add(array[i]);
- }
- return list;
- }
-
private static final String[] EMPTY_STRING_ARRAY = new String[0];
private static String[] filterOutEmptyString(final String[] array) {
@@ -291,7 +273,7 @@ public final class KeySpecParser {
final String entry = array[i];
if (TextUtils.isEmpty(entry)) {
if (out == null) {
- out = arrayAsList(array, 0, i);
+ out = CollectionUtils.arrayAsList(array, 0, i);
}
} else if (out != null) {
out.add(entry);
@@ -326,7 +308,7 @@ public final class KeySpecParser {
} else {
// Filter out excessive '%' marker.
if (out == null) {
- out = arrayAsList(moreKeys, 0, moreKeyIndex);
+ out = CollectionUtils.arrayAsList(moreKeys, 0, moreKeyIndex);
}
}
} else {
@@ -343,7 +325,7 @@ public final class KeySpecParser {
+ " moreKeys=" + Arrays.toString(moreKeys)
+ " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys));
}
- out = arrayAsList(additionalMoreKeys, additionalIndex, additionalCount);
+ out = CollectionUtils.arrayAsList(additionalMoreKeys, additionalIndex, additionalCount);
for (int i = 0; i < moreKeysCount; i++) {
out.add(moreKeys[i]);
}
@@ -355,7 +337,7 @@ public final class KeySpecParser {
+ " moreKeys=" + Arrays.toString(moreKeys)
+ " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys));
}
- out = arrayAsList(moreKeys, 0, moreKeysCount);
+ out = CollectionUtils.arrayAsList(moreKeys, 0, moreKeysCount);
for (int i = additionalIndex; i < additionalCount; i++) {
out.add(additionalMoreKeys[additionalIndex]);
}
@@ -376,68 +358,6 @@ public final class KeySpecParser {
}
}
- 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) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java
index e6a674334..a2242b841 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java
@@ -32,14 +32,14 @@ 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);
+ final String text = mTextsSet.resolveTextReference(a.getString(index));
return KeySpecParser.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..96a5b089f 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
@@ -18,6 +18,7 @@ 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.utils.CollectionUtils;
@@ -45,6 +46,10 @@ import java.util.HashMap;
* KeyboardTextsSet.java
*/
public final class KeyboardTextsSet {
+ public static final String PREFIX_TEXT = "!text/";
+ private static final char 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 +92,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..dd58e1ff4 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java
@@ -74,7 +74,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) {
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/utils/CollectionUtils.java b/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java
index cc25102ce..bbfa0f091 100644
--- a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java
@@ -102,4 +102,19 @@ public final class CollectionUtils {
public static <E> SparseArray<E> newSparseArray() {
return new SparseArray<E>();
}
+
+ public static <E> ArrayList<E> arrayAsList(final E[] array, final int start, final int end) {
+ if (array == null) {
+ throw new NullPointerException();
+ }
+ if (start < 0 || start > end || end > array.length) {
+ throw new IllegalArgumentException();
+ }
+
+ final ArrayList<E> list = newArrayList(end - start);
+ for (int i = start; i < end; i++) {
+ list.add(array[i]);
+ }
+ return list;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
index 8eff2e6e7..4a0823155 100644
--- a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
@@ -22,13 +22,11 @@ import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;
+import com.android.inputmethod.latin.R;
+
public final class ImportantNoticeUtils {
private static final String TAG = ImportantNoticeUtils.class.getSimpleName();
- // The current version number of an important notice.
- // This number must be incremented whenever users should see a new important notice.
- private static final int CURRENT_IMPORTANT_NOTICE_VERSION = 0;
-
// {@link SharedPreferences} name to save the last important notice version that has been
// displayed to users.
private static final String PREFERENCE_NAME = "important_notice";
@@ -60,16 +58,20 @@ public final class ImportantNoticeUtils {
return context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
}
+ private static int getCurrentImportantNoticeVersion(final Context context) {
+ return context.getResources().getInteger(R.integer.config_important_notice_version);
+ }
+
public static boolean hasNewImportantNotice(final Context context) {
final SharedPreferences prefs = getImportantNoticePreferences(context);
final int lastVersion = prefs.getInt(KEY_IMPORTANT_NOTICE_VERSION, 0);
- return CURRENT_IMPORTANT_NOTICE_VERSION > lastVersion;
+ return getCurrentImportantNoticeVersion(context) > lastVersion;
}
public static void updateLastImportantNoticeVersion(final Context context) {
final SharedPreferences prefs = getImportantNoticePreferences(context);
prefs.edit()
- .putInt(KEY_IMPORTANT_NOTICE_VERSION, CURRENT_IMPORTANT_NOTICE_VERSION)
+ .putInt(KEY_IMPORTANT_NOTICE_VERSION, getCurrentImportantNoticeVersion(context))
.apply();
}
}
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);
diff --git a/native/jni/src/suggest/core/dictionary/word_property.cpp b/native/jni/src/suggest/core/dictionary/word_property.cpp
index ed32bde8b..4a260a982 100644
--- a/native/jni/src/suggest/core/dictionary/word_property.cpp
+++ b/native/jni/src/suggest/core/dictionary/word_property.cpp
@@ -33,15 +33,16 @@ void WordProperty::outputProperties(JNIEnv *const env, jintArray outCodePoints,
jmethodID intToIntegerConstructorId = env->GetMethodID(integerClass, "<init>", "(I)V");
jclass arrayListClass = env->FindClass("java/util/ArrayList");
jmethodID addMethodId = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
- const int shortcutTargetCount = mShortcutTargets.size();
+ const int shortcutTargetCount = mShortcuts.size();
for (int i = 0; i < shortcutTargetCount; ++i) {
- jintArray shortcutTargetCodePointArray = env->NewIntArray(mShortcutTargets[i].size());
+ const std::vector<int> *const targetCodePoints = mShortcuts[i].getTargetCodePoints();
+ jintArray shortcutTargetCodePointArray = env->NewIntArray(targetCodePoints->size());
env->SetIntArrayRegion(shortcutTargetCodePointArray, 0 /* start */,
- mShortcutTargets[i].size(), &mShortcutTargets[i][0]);
+ targetCodePoints->size(), &targetCodePoints->at(0));
env->CallVoidMethod(outShortcutTargets, addMethodId, shortcutTargetCodePointArray);
env->DeleteLocalRef(shortcutTargetCodePointArray);
jobject integerProbability = env->NewObject(integerClass, intToIntegerConstructorId,
- mShortcutProbabilities[i]);
+ mShortcuts[i].getProbability());
env->CallVoidMethod(outShortcutProbabilities, addMethodId, integerProbability);
env->DeleteLocalRef(integerProbability);
}
diff --git a/native/jni/src/suggest/core/dictionary/word_property.h b/native/jni/src/suggest/core/dictionary/word_property.h
index dcac8536a..69c880861 100644
--- a/native/jni/src/suggest/core/dictionary/word_property.h
+++ b/native/jni/src/suggest/core/dictionary/word_property.h
@@ -28,23 +28,54 @@ namespace latinime {
// This class is used for returning information belonging to a word to java side.
class WordProperty {
public:
- // TODO: Add bigram information.
+ class BigramProperty {
+ public:
+ BigramProperty(const std::vector<int> *const targetCodePoints,
+ const int probability, const int timestamp, const int level, const int count)
+ : mTargetCodePoints(*targetCodePoints), mProbability(probability),
+ mTimestamp(timestamp), mLevel(level), mCount(count) {}
+
+ private:
+ std::vector<int> mTargetCodePoints;
+ int mProbability;
+ int mTimestamp;
+ int mLevel;
+ int mCount;
+ };
+
+ class ShortcutProperty {
+ public:
+ ShortcutProperty(const std::vector<int> *const targetCodePoints, const int probability)
+ : mTargetCodePoints(*targetCodePoints), mProbability(probability) {}
+
+ const std::vector<int> *getTargetCodePoints() const {
+ return &mTargetCodePoints;
+ }
+
+ int getProbability() const {
+ return mProbability;
+ }
+
+ private:
+ std::vector<int> mTargetCodePoints;
+ int mProbability;
+ };
+
// Invalid word.
WordProperty()
: mCodePoints(), mIsNotAWord(false), mIsBlacklisted(false),
mHasBigrams(false), mHasShortcuts(false), mProbability(NOT_A_PROBABILITY),
- mTimestamp(0), mLevel(0), mCount(0), mShortcutTargets(), mShortcutProbabilities() {}
+ mTimestamp(0), mLevel(0), mCount(0), mBigrams(), mShortcuts() {}
WordProperty(const std::vector<int> *const codePoints,
const bool isNotAWord, const bool isBlacklisted, const bool hasBigrams,
const bool hasShortcuts, const int probability, const int timestamp,
- const int level, const int count,
- const std::vector<std::vector<int> > *const shortcutTargets,
- const std::vector<int> *const shortcutProbabilities)
+ const int level, const int count, const std::vector<BigramProperty> *const bigrams,
+ const std::vector<ShortcutProperty> *const shortcuts)
: mCodePoints(*codePoints), mIsNotAWord(isNotAWord), mIsBlacklisted(isBlacklisted),
mHasBigrams(hasBigrams), mHasShortcuts(hasShortcuts), mProbability(probability),
- mTimestamp(timestamp), mLevel(level), mCount(count),
- mShortcutTargets(*shortcutTargets), mShortcutProbabilities(*shortcutProbabilities) {}
+ mTimestamp(timestamp), mLevel(level), mCount(count), mBigrams(*bigrams),
+ mShortcuts(*shortcuts) {}
void outputProperties(JNIEnv *const env, jintArray outCodePoints, jbooleanArray outFlags,
jintArray outProbability, jintArray outHistoricalInfo, jobject outShortcutTargets,
@@ -63,9 +94,8 @@ class WordProperty {
int mTimestamp;
int mLevel;
int mCount;
- // Shortcut
- std::vector<std::vector<int> > mShortcutTargets;
- std::vector<int> mShortcutProbabilities;
+ std::vector<BigramProperty> mBigrams;
+ std::vector<ShortcutProperty> mShortcuts;
};
} // namespace latinime
#endif // LATINIME_WORD_PROPERTY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
index 0b067e127..625b5349b 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
@@ -332,9 +332,10 @@ const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const code
mBuffers.get()->getProbabilityDictContent()->getProbabilityEntry(
ptNodeParams.getTerminalId());
const HistoricalInfo *const historicalInfo = probabilityEntry.getHistoricalInfo();
+ // TODO: Fetch bigram information.
+ std::vector<WordProperty::BigramProperty> bigrams;
// Fetch shortcut information.
- std::vector<std::vector<int> > shortcutTargets;
- std::vector<int> shortcutProbabilities;
+ std::vector<WordProperty::ShortcutProperty> shortcuts;
int shortcutPos = getShortcutPositionOfPtNode(ptNodePos);
if (shortcutPos != NOT_A_DICT_POS) {
int shortcutTarget[MAX_WORD_LENGTH];
@@ -347,15 +348,14 @@ const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const code
shortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, shortcutTarget,
&shortcutTargetLength, &shortcutProbability, &hasNext, &shortcutPos);
std::vector<int> target(shortcutTarget, shortcutTarget + shortcutTargetLength);
- shortcutTargets.push_back(target);
- shortcutProbabilities.push_back(shortcutProbability);
+ shortcuts.push_back(WordProperty::ShortcutProperty(&target, shortcutProbability));
}
}
return WordProperty(&codePointVector, ptNodeParams.isNotAWord(),
ptNodeParams.isBlacklisted(), ptNodeParams.hasBigrams(),
ptNodeParams.hasShortcutTargets(), ptNodeParams.getProbability(),
historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
- historicalInfo->getCount(), &shortcutTargets, &shortcutProbabilities);
+ historicalInfo->getCount(), &bigrams, &shortcuts);
}
} // namespace latinime
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserSplitTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserSplitTests.java
index cbe2d5960..7b7f1758c 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserSplitTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserSplitTests.java
@@ -92,7 +92,7 @@ public class KeySpecParserSplitTests extends InstrumentationTestCase {
private void assertTextArray(final String message, final String value,
final String ... expectedArray) {
- final String resolvedActual = KeySpecParser.resolveTextReference(value, mTextsSet);
+ final String resolvedActual = mTextsSet.resolveTextReference(value);
final String[] actual = KeySpecParser.splitKeySpecs(resolvedActual);
final String[] expected = (expectedArray.length == 0) ? null : expectedArray;
assertArrayEquals(message, expected, actual);
@@ -117,13 +117,11 @@ public class KeySpecParserSplitTests extends InstrumentationTestCase {
private static final String SURROGATE2 = PAIR1 + PAIR2 + PAIR3;
public void testResolveNullText() {
- assertNull("resolve null", KeySpecParser.resolveTextReference(
- null, mTextsSet));
+ assertNull("resolve null", mTextsSet.resolveTextReference(null));
}
public void testResolveEmptyText() {
- assertNull("resolve empty text", KeySpecParser.resolveTextReference(
- "!text/empty_string", mTextsSet));
+ assertNull("resolve empty text", mTextsSet.resolveTextReference("!text/empty_string"));
}
public void testSplitZero() {
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java
index afb2b0343..0388435eb 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java
@@ -73,7 +73,7 @@ public class KeySpecParserTests extends AndroidTestCase {
private void assertParser(String message, String moreKeySpec, String expectedLabel,
String expectedOutputText, int expectedIcon, int expectedCode) {
- final String labelResolved = KeySpecParser.resolveTextReference(moreKeySpec, mTextsSet);
+ final String labelResolved = mTextsSet.resolveTextReference(moreKeySpec);
final MoreKeySpec spec = new MoreKeySpec(labelResolved, false /* needsToUpperCase */,
Locale.US, mCodesSet);
assertEquals(message + " [label]", expectedLabel, spec.mLabel);
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
index c42765633..343ab420c 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
@@ -102,13 +102,13 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
getContext().getCacheDir());
FileUtils.deleteRecursively(file);
Map<String, String> attributeMap = new HashMap<String, String>();
- attributeMap.put(FormatSpec.FileHeader.DICTIONARY_ID_ATTRIBUTE, dictId);
- attributeMap.put(FormatSpec.FileHeader.DICTIONARY_LOCALE_ATTRIBUTE, dictId);
- attributeMap.put(FormatSpec.FileHeader.DICTIONARY_VERSION_ATTRIBUTE,
+ attributeMap.put(FormatSpec.FileHeader.DICTIONARY_ID_KEY, dictId);
+ attributeMap.put(FormatSpec.FileHeader.DICTIONARY_LOCALE_KEY, dictId);
+ attributeMap.put(FormatSpec.FileHeader.DICTIONARY_VERSION_KEY,
String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())));
- 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);
if (BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(),
FormatSpec.VERSION4, attributeMap)) {
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java
index f17596865..20cf9a562 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java
@@ -39,13 +39,13 @@ public class BinaryDictUtils {
public static DictionaryOptions makeDictionaryOptions(final String id, final String version,
final FormatSpec.FormatOptions formatOptions) {
final DictionaryOptions options = new DictionaryOptions(new HashMap<String, String>());
- options.mAttributes.put(FileHeader.DICTIONARY_LOCALE_ATTRIBUTE, "en_US");
- options.mAttributes.put(FileHeader.DICTIONARY_ID_ATTRIBUTE, id);
- options.mAttributes.put(FileHeader.DICTIONARY_VERSION_ATTRIBUTE, version);
+ options.mAttributes.put(FileHeader.DICTIONARY_LOCALE_KEY, "en_US");
+ options.mAttributes.put(FileHeader.DICTIONARY_ID_KEY, id);
+ options.mAttributes.put(FileHeader.DICTIONARY_VERSION_KEY, version);
if (formatOptions.mHasTimestamp) {
- options.mAttributes.put(FileHeader.HAS_HISTORICAL_INFO_ATTRIBUTE,
+ options.mAttributes.put(FileHeader.HAS_HISTORICAL_INFO_KEY,
FileHeader.ATTRIBUTE_VALUE_TRUE);
- options.mAttributes.put(FileHeader.USES_FORGETTING_CURVE_ATTRIBUTE,
+ options.mAttributes.put(FileHeader.USES_FORGETTING_CURVE_KEY,
FileHeader.ATTRIBUTE_VALUE_TRUE);
}
return options;
diff --git a/tests/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtilsTests.java
index ae08b49d7..93731b3cd 100644
--- a/tests/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtilsTests.java
@@ -56,9 +56,9 @@ public class UserHistoryDictIOUtilsTests extends AndroidTestCase
private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
private static final HashMap<String, String> HEADER_OPTIONS = new HashMap<String, String>();
static {
- HEADER_OPTIONS.put(FileHeader.DICTIONARY_LOCALE_ATTRIBUTE, "en_US");
- HEADER_OPTIONS.put(FileHeader.DICTIONARY_ID_ATTRIBUTE, "test");
- HEADER_OPTIONS.put(FileHeader.DICTIONARY_VERSION_ATTRIBUTE, "1000");
+ HEADER_OPTIONS.put(FileHeader.DICTIONARY_LOCALE_KEY, "en_US");
+ HEADER_OPTIONS.put(FileHeader.DICTIONARY_ID_KEY, "test");
+ HEADER_OPTIONS.put(FileHeader.DICTIONARY_VERSION_KEY, "1000");
}
/**
diff --git a/tools/dicttool/Android.mk b/tools/dicttool/Android.mk
index b7b1fe6cd..adfb920dd 100644
--- a/tools/dicttool/Android.mk
+++ b/tools/dicttool/Android.mk
@@ -49,7 +49,7 @@ USED_TARGETTED_UTILS := \
$(LATINIME_CORE_SOURCE_DIRECTORY)/utils/LocaleUtils.java \
$(LATINIME_CORE_SOURCE_DIRECTORY)/utils/ResizableIntArray.java \
$(LATINIME_CORE_SOURCE_DIRECTORY)/utils/StringUtils.java \
- $(LATINIME_CORE_SOURCE_DIRECTORY)/utils/UnigramProperty.java
+ $(LATINIME_CORE_SOURCE_DIRECTORY)/utils/WordProperty.java
DICTTOOL_ONDEVICE_TESTS_DIRECTORY := \
$(LATINIME_LOCAL_DIR)/tests/src/com/android/inputmethod/latin/makedict/
diff --git a/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java b/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java
index 0c11f868e..d8059e428 100644
--- a/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java
+++ b/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java
@@ -48,9 +48,9 @@ public class BinaryDictOffdeviceUtilsTests extends TestCase {
// Create a thrice-compressed dictionary file.
final DictionaryOptions testOptions = new DictionaryOptions(new HashMap<String, String>());
- testOptions.mAttributes.put(FormatSpec.FileHeader.DICTIONARY_VERSION_ATTRIBUTE, VERSION);
- testOptions.mAttributes.put(FormatSpec.FileHeader.DICTIONARY_LOCALE_ATTRIBUTE, LOCALE);
- testOptions.mAttributes.put(FormatSpec.FileHeader.DICTIONARY_ID_ATTRIBUTE, ID);
+ testOptions.mAttributes.put(FormatSpec.FileHeader.DICTIONARY_VERSION_KEY, VERSION);
+ testOptions.mAttributes.put(FormatSpec.FileHeader.DICTIONARY_LOCALE_KEY, LOCALE);
+ testOptions.mAttributes.put(FormatSpec.FileHeader.DICTIONARY_ID_KEY, ID);
final FusionDictionary dict = new FusionDictionary(new PtNodeArray(), testOptions);
dict.add("foo", TEST_FREQ, null, false /* isNotAWord */);
dict.add("fta", 1, null, false /* isNotAWord */);
@@ -80,11 +80,11 @@ public class BinaryDictOffdeviceUtilsTests extends TestCase {
null /* dict : an optional dictionary to add words to, or null */,
false /* deleteDictIfBroken */);
assertEquals("Wrong version attribute", VERSION, resultDict.mOptions.mAttributes.get(
- FormatSpec.FileHeader.DICTIONARY_VERSION_ATTRIBUTE));
+ FormatSpec.FileHeader.DICTIONARY_VERSION_KEY));
assertEquals("Wrong locale attribute", LOCALE, resultDict.mOptions.mAttributes.get(
- FormatSpec.FileHeader.DICTIONARY_LOCALE_ATTRIBUTE));
+ FormatSpec.FileHeader.DICTIONARY_LOCALE_KEY));
assertEquals("Wrong id attribute", ID, resultDict.mOptions.mAttributes.get(
- FormatSpec.FileHeader.DICTIONARY_ID_ATTRIBUTE));
+ FormatSpec.FileHeader.DICTIONARY_ID_KEY));
assertEquals("Dictionary can't be read back correctly",
FusionDictionary.findWordInTree(resultDict.mRootNodeArray, "foo").getFrequency(),
TEST_FREQ);
diff --git a/tools/make-keyboard-text/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl b/tools/make-keyboard-text/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl
index a8ac981e0..92529925d 100644
--- a/tools/make-keyboard-text/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl
+++ b/tools/make-keyboard-text/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl
@@ -18,6 +18,7 @@ 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.utils.CollectionUtils;
@@ -45,6 +46,10 @@ import java.util.HashMap;
* KeyboardTextsSet.java
*/
public final class KeyboardTextsSet {
+ public static final String PREFIX_TEXT = "!text/";
+ private static final char 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 +92,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 = {