Merge "Move some methods to StringUtils"
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index e66cfca..95823da 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -27,7 +27,7 @@
 import com.android.inputmethod.latin.utils.JniUtils;
 import com.android.inputmethod.latin.utils.LanguageModelParam;
 import com.android.inputmethod.latin.utils.StringUtils;
-import com.android.inputmethod.latin.utils.UnigramProperty;
+import com.android.inputmethod.latin.utils.WordProperty;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -61,18 +61,18 @@
 
     public static final int NOT_A_VALID_TIMESTAMP = -1;
 
-    // Format to get unigram flags from native side via getUnigramPropertyNative().
-    private static final int FORMAT_UNIGRAM_PROPERTY_OUTPUT_FLAG_COUNT = 4;
-    private static final int FORMAT_UNIGRAM_PROPERTY_IS_NOT_A_WORD_INDEX = 0;
-    private static final int FORMAT_UNIGRAM_PROPERTY_IS_BLACKLISTED_INDEX = 1;
-    private static final int FORMAT_UNIGRAM_PROPERTY_HAS_BIGRAMS_INDEX = 2;
-    private static final int FORMAT_UNIGRAM_PROPERTY_HAS_SHORTCUTS_INDEX = 3;
+    // Format to get unigram flags from native side via getWordPropertyNative().
+    private static final int FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT = 4;
+    private static final int FORMAT_WORD_PROPERTY_IS_NOT_A_WORD_INDEX = 0;
+    private static final int FORMAT_WORD_PROPERTY_IS_BLACKLISTED_INDEX = 1;
+    private static final int FORMAT_WORD_PROPERTY_HAS_BIGRAMS_INDEX = 2;
+    private static final int FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX = 3;
 
-    // Format to get unigram historical info from native side via getUnigramPropertyNative().
-    private static final int FORMAT_UNIGRAM_PROPERTY_OUTPUT_HISTORICAL_INFO_COUNT = 3;
-    private static final int FORMAT_UNIGRAM_PROPERTY_TIMESTAMP_INDEX = 0;
-    private static final int FORMAT_UNIGRAM_PROPERTY_LEVEL_INDEX = 1;
-    private static final int FORMAT_UNIGRAM_PROPERTY_COUNT_INDEX = 2;
+    // Format to get unigram historical info from native side via getWordPropertyNative().
+    private static final int FORMAT_WORD_PROPERTY_OUTPUT_HISTORICAL_INFO_COUNT = 3;
+    private static final int FORMAT_WORD_PROPERTY_TIMESTAMP_INDEX = 0;
+    private static final int FORMAT_WORD_PROPERTY_LEVEL_INDEX = 1;
+    private static final int FORMAT_WORD_PROPERTY_COUNT_INDEX = 2;
 
     private long mNativeDict;
     private final Locale mLocale;
@@ -143,7 +143,7 @@
     private static native int getFormatVersionNative(long dict);
     private static native int getProbabilityNative(long dict, int[] word);
     private static native int getBigramProbabilityNative(long dict, int[] word0, int[] word1);
-    private static native void getUnigramPropertyNative(long dict, int[] word,
+    private static native void getWordPropertyNative(long dict, int[] word,
             int[] outCodePoints, boolean[] outFlags, int[] outProbability,
             int[] outHistoricalInfo, ArrayList<int[]> outShortcutTargets,
             ArrayList<Integer> outShortcutProbabilities);
@@ -306,28 +306,28 @@
     }
 
     @UsedForTesting
-    public UnigramProperty getUnigramProperty(final String word) {
+    public WordProperty getWordProperty(final String word) {
         if (TextUtils.isEmpty(word)) {
             return null;
         }
         final int[] codePoints = StringUtils.toCodePointArray(word);
         final int[] outCodePoints = new int[MAX_WORD_LENGTH];
-        final boolean[] outFlags = new boolean[FORMAT_UNIGRAM_PROPERTY_OUTPUT_FLAG_COUNT];
+        final boolean[] outFlags = new boolean[FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT];
         final int[] outProbability = new int[1];
         final int[] outHistoricalInfo =
-                new int[FORMAT_UNIGRAM_PROPERTY_OUTPUT_HISTORICAL_INFO_COUNT];
+                new int[FORMAT_WORD_PROPERTY_OUTPUT_HISTORICAL_INFO_COUNT];
         final ArrayList<int[]> outShortcutTargets = CollectionUtils.newArrayList();
         final ArrayList<Integer> outShortcutProbabilities = CollectionUtils.newArrayList();
-        getUnigramPropertyNative(mNativeDict, codePoints, outCodePoints, outFlags, outProbability,
+        getWordPropertyNative(mNativeDict, codePoints, outCodePoints, outFlags, outProbability,
                 outHistoricalInfo, outShortcutTargets, outShortcutProbabilities);
-        return new UnigramProperty(codePoints,
-                outFlags[FORMAT_UNIGRAM_PROPERTY_IS_NOT_A_WORD_INDEX],
-                outFlags[FORMAT_UNIGRAM_PROPERTY_IS_BLACKLISTED_INDEX],
-                outFlags[FORMAT_UNIGRAM_PROPERTY_HAS_BIGRAMS_INDEX],
-                outFlags[FORMAT_UNIGRAM_PROPERTY_HAS_SHORTCUTS_INDEX], outProbability[0],
-                outHistoricalInfo[FORMAT_UNIGRAM_PROPERTY_TIMESTAMP_INDEX],
-                outHistoricalInfo[FORMAT_UNIGRAM_PROPERTY_LEVEL_INDEX],
-                outHistoricalInfo[FORMAT_UNIGRAM_PROPERTY_COUNT_INDEX],
+        return new WordProperty(codePoints,
+                outFlags[FORMAT_WORD_PROPERTY_IS_NOT_A_WORD_INDEX],
+                outFlags[FORMAT_WORD_PROPERTY_IS_BLACKLISTED_INDEX],
+                outFlags[FORMAT_WORD_PROPERTY_HAS_BIGRAMS_INDEX],
+                outFlags[FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX], outProbability[0],
+                outHistoricalInfo[FORMAT_WORD_PROPERTY_TIMESTAMP_INDEX],
+                outHistoricalInfo[FORMAT_WORD_PROPERTY_LEVEL_INDEX],
+                outHistoricalInfo[FORMAT_WORD_PROPERTY_COUNT_INDEX],
                 outShortcutTargets, outShortcutProbabilities);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java
index db628fe..a6ae640 100644
--- a/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java
@@ -46,7 +46,7 @@
     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 LAST_UPDATED_TIME_KEY = "date";
+    private static final String DATE_KEY = "date";
 
     public interface OnAddWordListener {
         /**
@@ -76,7 +76,7 @@
             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(LAST_UPDATED_TIME_KEY,
+        fusionDict.addOptionAttribute(DATE_KEY,
                 String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())));
         try {
             dictEncoder.writeDictionary(fusionDict, formatOptions);
diff --git a/java/src/com/android/inputmethod/latin/utils/UnigramProperty.java b/java/src/com/android/inputmethod/latin/utils/WordProperty.java
similarity index 93%
rename from java/src/com/android/inputmethod/latin/utils/UnigramProperty.java
rename to java/src/com/android/inputmethod/latin/utils/WordProperty.java
index 4feee43..d6c0f90 100644
--- a/java/src/com/android/inputmethod/latin/utils/UnigramProperty.java
+++ b/java/src/com/android/inputmethod/latin/utils/WordProperty.java
@@ -26,7 +26,7 @@
 // This has information that belong to a unigram. This class has some detailed attributes such as
 // historical information but they have to be checked only for testing purpose.
 @UsedForTesting
-public class UnigramProperty {
+public class WordProperty {
     public final String mCodePoints;
     public final boolean mIsNotAWord;
     public final boolean mIsBlacklisted;
@@ -50,8 +50,8 @@
         return codePoints.length;
     }
 
-    // This represents invalid unigram when the probability is BinaryDictionary.NOT_A_PROBABILITY.
-    public UnigramProperty(final int[] codePoints, final boolean isNotAWord,
+    // This represents invalid word when the probability is BinaryDictionary.NOT_A_PROBABILITY.
+    public WordProperty(final int[] codePoints, final boolean isNotAWord,
             final boolean isBlacklisted, final boolean hasBigram,
             final boolean hasShortcuts, final int probability, final int timestamp,
             final int level, final int count, final ArrayList<int[]> shortcutTargets,
diff --git a/native/jni/NativeFileList.mk b/native/jni/NativeFileList.mk
index d2f2259..c7061c8 100644
--- a/native/jni/NativeFileList.mk
+++ b/native/jni/NativeFileList.mk
@@ -32,7 +32,7 @@
         error_type_utils.cpp \
         multi_bigram_map.cpp \
         suggestions_output_utils.cpp \
-        unigram_property.cpp) \
+        word_property.cpp) \
     $(addprefix suggest/core/layout/, \
         additional_proximity_chars.cpp \
         proximity_info.cpp \
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 586a306..16a3fe8 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -24,7 +24,7 @@
 #include "jni.h"
 #include "jni_common.h"
 #include "suggest/core/dictionary/dictionary.h"
-#include "suggest/core/dictionary/unigram_property.h"
+#include "suggest/core/dictionary/word_property.h"
 #include "suggest/core/suggest_options.h"
 #include "suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h"
 #include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
@@ -260,7 +260,7 @@
             word1Length);
 }
 
-static void latinime_BinaryDictionary_getUnigramProperty(JNIEnv *env, jclass clazz,
+static void latinime_BinaryDictionary_getWordProperty(JNIEnv *env, jclass clazz,
         jlong dict, jintArray word, jintArray outCodePoints, jbooleanArray outFlags,
         jintArray outProbability, jintArray outHistoricalInfo, jobject outShortcutTargets,
         jobject outShortcutProbabilities) {
@@ -269,9 +269,8 @@
     const jsize wordLength = env->GetArrayLength(word);
     int wordCodePoints[wordLength];
     env->GetIntArrayRegion(word, 0, wordLength, wordCodePoints);
-    const UnigramProperty unigramProperty = dictionary->getUnigramProperty(
-            wordCodePoints, wordLength);
-    unigramProperty.outputProperties(env, outCodePoints, outFlags, outProbability,
+    const WordProperty wordProperty = dictionary->getWordProperty(wordCodePoints, wordLength);
+    wordProperty.outputProperties(env, outCodePoints, outFlags, outProbability,
             outHistoricalInfo, outShortcutTargets, outShortcutProbabilities);
 }
 
@@ -521,9 +520,9 @@
         reinterpret_cast<void *>(latinime_BinaryDictionary_getBigramProbability)
     },
     {
-        const_cast<char *>("getUnigramPropertyNative"),
+        const_cast<char *>("getWordPropertyNative"),
         const_cast<char *>("(J[I[I[Z[I[ILjava/util/ArrayList;Ljava/util/ArrayList;)V"),
-        reinterpret_cast<void *>(latinime_BinaryDictionary_getUnigramProperty)
+        reinterpret_cast<void *>(latinime_BinaryDictionary_getWordProperty)
     },
     {
         const_cast<char *>("calcNormalizedScoreNative"),
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.cpp b/native/jni/src/suggest/core/dictionary/dictionary.cpp
index e68c0a6..16b1a56 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.cpp
+++ b/native/jni/src/suggest/core/dictionary/dictionary.cpp
@@ -143,10 +143,10 @@
             maxResultLength);
 }
 
-const UnigramProperty Dictionary::getUnigramProperty(const int *const codePoints,
+const WordProperty Dictionary::getWordProperty(const int *const codePoints,
         const int codePointCount) {
     TimeKeeper::setCurrentTime();
-    return mDictionaryStructureWithBufferPolicy.get()->getUnigramProperty(
+    return mDictionaryStructureWithBufferPolicy.get()->getWordProperty(
             codePoints, codePointCount);
 }
 
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.h b/native/jni/src/suggest/core/dictionary/dictionary.h
index b37b4aa..4a468f3 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.h
+++ b/native/jni/src/suggest/core/dictionary/dictionary.h
@@ -22,7 +22,7 @@
 #include "defines.h"
 #include "jni.h"
 #include "suggest/core/dictionary/bigram_dictionary.h"
-#include "suggest/core/dictionary/unigram_property.h"
+#include "suggest/core/dictionary/word_property.h"
 #include "suggest/core/policy/dictionary_header_structure_policy.h"
 #include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
 #include "suggest/core/suggest_interface.h"
@@ -34,7 +34,7 @@
 class DicTraverseSession;
 class ProximityInfo;
 class SuggestOptions;
-class UnigramProperty;
+class WordProperty;
 
 class Dictionary {
  public:
@@ -94,7 +94,7 @@
     void getProperty(const char *const query, const int queryLength, char *const outResult,
             const int maxResultLength);
 
-    const UnigramProperty getUnigramProperty(const int *const codePoints, const int codePointCount);
+    const WordProperty getWordProperty(const int *const codePoints, const int codePointCount);
 
     const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const {
         return mDictionaryStructureWithBufferPolicy.get();
diff --git a/native/jni/src/suggest/core/dictionary/unigram_property.h b/native/jni/src/suggest/core/dictionary/unigram_property.h
deleted file mode 100644
index c4ebb86..0000000
--- a/native/jni/src/suggest/core/dictionary/unigram_property.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LATINIME_UNIGRAM_PROPERTY_H
-#define LATINIME_UNIGRAM_PROPERTY_H
-
-#include <cstring>
-#include <vector>
-
-#include "defines.h"
-#include "jni.h"
-
-namespace latinime {
-
-// This class is used for returning information belonging to a unigram to java side.
-class UnigramProperty {
- public:
-    // Invalid unigram.
-    UnigramProperty()
-            : mCodePoints(), mCodePointCount(0), mIsNotAWord(false), mIsBlacklisted(false),
-              mHasBigrams(false), mHasShortcuts(false), mProbability(NOT_A_PROBABILITY),
-              mTimestamp(0), mLevel(0), mCount(0), mShortcutTargets(), mShortcutProbabilities() {}
-
-    UnigramProperty(const UnigramProperty &unigramProperty)
-            : mCodePoints(), mCodePointCount(unigramProperty.mCodePointCount),
-              mIsNotAWord(unigramProperty.mIsNotAWord),
-              mIsBlacklisted(unigramProperty.mIsBlacklisted),
-              mHasBigrams(unigramProperty.mHasBigrams),
-              mHasShortcuts(unigramProperty.mHasShortcuts),
-              mProbability(unigramProperty.mProbability),
-              mTimestamp(unigramProperty.mTimestamp), mLevel(unigramProperty.mLevel),
-              mCount(unigramProperty.mCount), mShortcutTargets(unigramProperty.mShortcutTargets),
-              mShortcutProbabilities(unigramProperty.mShortcutProbabilities) {
-        memcpy(mCodePoints, unigramProperty.mCodePoints, sizeof(mCodePoints));
-    }
-
-    UnigramProperty(const int *const codePoints, const int codePointCount,
-            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)
-            : mCodePoints(), mCodePointCount(codePointCount),
-              mIsNotAWord(isNotAWord), mIsBlacklisted(isBlacklisted), mHasBigrams(hasBigrams),
-              mHasShortcuts(hasShortcuts), mProbability(probability), mTimestamp(timestamp),
-              mLevel(level), mCount(count), mShortcutTargets(*shortcutTargets),
-              mShortcutProbabilities(*shortcutProbabilities) {
-        memcpy(mCodePoints, codePoints, sizeof(mCodePoints));
-    }
-
-    void outputProperties(JNIEnv *const env, jintArray outCodePoints, jbooleanArray outFlags,
-            jintArray outProbability, jintArray outHistoricalInfo, jobject outShortcutTargets,
-            jobject outShortcutProbabilities) const;
-
- private:
-    DISALLOW_ASSIGNMENT_OPERATOR(UnigramProperty);
-
-    int mCodePoints[MAX_WORD_LENGTH];
-    int mCodePointCount;
-    bool mIsNotAWord;
-    bool mIsBlacklisted;
-    bool mHasBigrams;
-    bool mHasShortcuts;
-    int mProbability;
-    // Historical information
-    int mTimestamp;
-    int mLevel;
-    int mCount;
-    // Shortcut
-    std::vector<std::vector<int> > mShortcutTargets;
-    std::vector<int> mShortcutProbabilities;
-};
-} // namespace latinime
-#endif // LATINIME_UNIGRAM_PROPERTY_H
diff --git a/native/jni/src/suggest/core/dictionary/unigram_property.cpp b/native/jni/src/suggest/core/dictionary/word_property.cpp
similarity index 93%
rename from native/jni/src/suggest/core/dictionary/unigram_property.cpp
rename to native/jni/src/suggest/core/dictionary/word_property.cpp
index 16bbb69..ed32bde 100644
--- a/native/jni/src/suggest/core/dictionary/unigram_property.cpp
+++ b/native/jni/src/suggest/core/dictionary/word_property.cpp
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#include "suggest/core/dictionary/unigram_property.h"
+#include "suggest/core/dictionary/word_property.h"
 
 namespace latinime {
 
-void UnigramProperty::outputProperties(JNIEnv *const env, jintArray outCodePoints,
+void WordProperty::outputProperties(JNIEnv *const env, jintArray outCodePoints,
         jbooleanArray outFlags, jintArray outProbability, jintArray outHistoricalInfo,
         jobject outShortcutTargets, jobject outShortcutProbabilities) const {
-    env->SetIntArrayRegion(outCodePoints, 0 /* start */, mCodePointCount, mCodePoints);
+    env->SetIntArrayRegion(outCodePoints, 0 /* start */, mCodePoints.size(), &mCodePoints[0]);
     jboolean flags[] = {mIsNotAWord, mIsBlacklisted, mHasBigrams, mHasShortcuts};
     env->SetBooleanArrayRegion(outFlags, 0 /* start */, NELEMS(flags), flags);
     env->SetIntArrayRegion(outProbability, 0 /* start */, 1 /* len */, &mProbability);
diff --git a/native/jni/src/suggest/core/dictionary/word_property.h b/native/jni/src/suggest/core/dictionary/word_property.h
new file mode 100644
index 0000000..dcac853
--- /dev/null
+++ b/native/jni/src/suggest/core/dictionary/word_property.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_WORD_PROPERTY_H
+#define LATINIME_WORD_PROPERTY_H
+
+#include <cstring>
+#include <vector>
+
+#include "defines.h"
+#include "jni.h"
+
+namespace latinime {
+
+// This class is used for returning information belonging to a word to java side.
+class WordProperty {
+ public:
+    // TODO: Add bigram information.
+    // Invalid word.
+    WordProperty()
+            : mCodePoints(), mIsNotAWord(false), mIsBlacklisted(false),
+              mHasBigrams(false), mHasShortcuts(false), mProbability(NOT_A_PROBABILITY),
+              mTimestamp(0), mLevel(0), mCount(0), mShortcutTargets(), mShortcutProbabilities() {}
+
+    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)
+            : mCodePoints(*codePoints), mIsNotAWord(isNotAWord), mIsBlacklisted(isBlacklisted),
+              mHasBigrams(hasBigrams), mHasShortcuts(hasShortcuts), mProbability(probability),
+              mTimestamp(timestamp), mLevel(level), mCount(count),
+              mShortcutTargets(*shortcutTargets), mShortcutProbabilities(*shortcutProbabilities) {}
+
+    void outputProperties(JNIEnv *const env, jintArray outCodePoints, jbooleanArray outFlags,
+            jintArray outProbability, jintArray outHistoricalInfo, jobject outShortcutTargets,
+            jobject outShortcutProbabilities) const;
+
+ private:
+    DISALLOW_ASSIGNMENT_OPERATOR(WordProperty);
+
+    std::vector<int> mCodePoints;
+    bool mIsNotAWord;
+    bool mIsBlacklisted;
+    bool mHasBigrams;
+    bool mHasShortcuts;
+    int mProbability;
+    // Historical information
+    int mTimestamp;
+    int mLevel;
+    int mCount;
+    // Shortcut
+    std::vector<std::vector<int> > mShortcutTargets;
+    std::vector<int> mShortcutProbabilities;
+};
+} // namespace latinime
+#endif // LATINIME_WORD_PROPERTY_H
diff --git a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
index c74a4eb..b878984 100644
--- a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
+++ b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
@@ -18,7 +18,7 @@
 #define LATINIME_DICTIONARY_STRUCTURE_POLICY_H
 
 #include "defines.h"
-#include "suggest/core/dictionary/unigram_property.h"
+#include "suggest/core/dictionary/word_property.h"
 #include "utils/exclusive_ownership_pointer.h"
 
 namespace latinime {
@@ -92,7 +92,7 @@
             const int maxResultLength) = 0;
 
     // Used for testing.
-    virtual const UnigramProperty getUnigramProperty(const int *const codePonts,
+    virtual const WordProperty getWordProperty(const int *const codePonts,
             const int codePointCount) const = 0;
 
  protected:
diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp
index 37a5b3f..7504524 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp
@@ -24,7 +24,7 @@
         "REQUIRES_GERMAN_UMLAUT_PROCESSING";
 // TODO: Change attribute string to "IS_DECAYING_DICT".
 const char *const HeaderPolicy::IS_DECAYING_DICT_KEY = "USES_FORGETTING_CURVE";
-const char *const HeaderPolicy::LAST_UPDATED_TIME_KEY = "date";
+const char *const HeaderPolicy::DATE_KEY = "date";
 const char *const HeaderPolicy::LAST_DECAYED_TIME_KEY = "LAST_DECAYED_TIME";
 const char *const HeaderPolicy::UNIGRAM_COUNT_KEY = "UNIGRAM_COUNT";
 const char *const HeaderPolicy::BIGRAM_COUNT_KEY = "BIGRAM_COUNT";
@@ -73,13 +73,13 @@
             REQUIRES_GERMAN_UMLAUT_PROCESSING_KEY, false);
 }
 
-bool HeaderPolicy::fillInAndWriteHeaderToBuffer(const bool updatesLastUpdatedTime,
-        const bool updatesLastDecayedTime, const int unigramCount, const int bigramCount,
+bool HeaderPolicy::fillInAndWriteHeaderToBuffer(const bool updatesLastDecayedTime,
+        const int unigramCount, const int bigramCount,
         const int extendedRegionSize, BufferWithExtendableBuffer *const outBuffer) const {
     int writingPos = 0;
     HeaderReadWriteUtils::AttributeMap attributeMapToWrite(mAttributeMap);
-    fillInHeader(updatesLastDecayedTime, updatesLastDecayedTime,
-            unigramCount, bigramCount, extendedRegionSize, &attributeMapToWrite);
+    fillInHeader(updatesLastDecayedTime, unigramCount, bigramCount,
+            extendedRegionSize, &attributeMapToWrite);
     if (!HeaderReadWriteUtils::writeDictionaryVersion(outBuffer, mDictFormatVersion,
             &writingPos)) {
         return false;
@@ -106,18 +106,16 @@
     return true;
 }
 
-void HeaderPolicy::fillInHeader(const bool updatesLastUpdatedTime,
-        const bool updatesLastDecayedTime, const int unigramCount, const int bigramCount,
-        const int extendedRegionSize, HeaderReadWriteUtils::AttributeMap *outAttributeMap) const {
+void HeaderPolicy::fillInHeader(const bool updatesLastDecayedTime, const int unigramCount,
+        const int bigramCount, const int extendedRegionSize,
+        HeaderReadWriteUtils::AttributeMap *outAttributeMap) const {
     HeaderReadWriteUtils::setIntAttribute(outAttributeMap, UNIGRAM_COUNT_KEY, unigramCount);
     HeaderReadWriteUtils::setIntAttribute(outAttributeMap, BIGRAM_COUNT_KEY, bigramCount);
     HeaderReadWriteUtils::setIntAttribute(outAttributeMap, EXTENDED_REGION_SIZE_KEY,
             extendedRegionSize);
-    if (updatesLastUpdatedTime) {
-        // Set current time as the last updated time.
-        HeaderReadWriteUtils::setIntAttribute(outAttributeMap, LAST_UPDATED_TIME_KEY,
-                TimeKeeper::peekCurrentTime());
-    }
+    // Set the current time as the generation time.
+    HeaderReadWriteUtils::setIntAttribute(outAttributeMap, DATE_KEY,
+            TimeKeeper::peekCurrentTime());
     if (updatesLastDecayedTime) {
         // Set current time as the last updated time.
         HeaderReadWriteUtils::setIntAttribute(outAttributeMap, LAST_DECAYED_TIME_KEY,
diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
index d653152..a44f9f0 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
@@ -39,8 +39,8 @@
               mRequiresGermanUmlautProcessing(readRequiresGermanUmlautProcessing()),
               mIsDecayingDict(HeaderReadWriteUtils::readBoolAttributeValue(&mAttributeMap,
                       IS_DECAYING_DICT_KEY, false /* defaultValue */)),
-              mLastUpdatedTime(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
-                      LAST_UPDATED_TIME_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
+              mDate(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
+                      DATE_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
               mLastDecayedTime(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
                       LAST_DECAYED_TIME_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
               mUnigramCount(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
@@ -62,10 +62,10 @@
               mRequiresGermanUmlautProcessing(readRequiresGermanUmlautProcessing()),
               mIsDecayingDict(HeaderReadWriteUtils::readBoolAttributeValue(&mAttributeMap,
                       IS_DECAYING_DICT_KEY, false /* defaultValue */)),
-              mLastUpdatedTime(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
-                      LAST_UPDATED_TIME_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
+              mDate(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
+                      DATE_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
               mLastDecayedTime(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
-                      LAST_UPDATED_TIME_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
+                      DATE_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
               mUnigramCount(0), mBigramCount(0), mExtendedRegionSize(0),
               mHasHistoricalInfoOfWords(HeaderReadWriteUtils::readBoolAttributeValue(
                       &mAttributeMap, HAS_HISTORICAL_INFO_KEY, false /* defaultValue */)) {}
@@ -75,7 +75,7 @@
             : mDictFormatVersion(FormatUtils::UNKNOWN_VERSION), mDictionaryFlags(0), mSize(0),
               mAttributeMap(), mMultiWordCostMultiplier(0.0f),
               mRequiresGermanUmlautProcessing(false), mIsDecayingDict(false),
-              mLastUpdatedTime(0), mLastDecayedTime(0), mUnigramCount(0), mBigramCount(0),
+              mDate(0), mLastDecayedTime(0), mUnigramCount(0), mBigramCount(0),
               mExtendedRegionSize(0), mHasHistoricalInfoOfWords(false) {}
 
     ~HeaderPolicy() {}
@@ -122,8 +122,8 @@
         return mRequiresGermanUmlautProcessing;
     }
 
-    AK_FORCE_INLINE int getLastUpdatedTime() const {
-        return mLastUpdatedTime;
+    AK_FORCE_INLINE int getDate() const {
+        return mDate;
     }
 
     AK_FORCE_INLINE int getLastDecayedTime() const {
@@ -149,11 +149,11 @@
     void readHeaderValueOrQuestionMark(const char *const key,
             int *outValue, int outValueSize) const;
 
-    bool fillInAndWriteHeaderToBuffer(const bool updatesLastUpdatedTime,
-            const bool updatesLastDecayedTime, const int unigramCount, const int bigramCount,
+    bool fillInAndWriteHeaderToBuffer(const bool updatesLastDecayedTime,
+            const int unigramCount, const int bigramCount,
             const int extendedRegionSize, BufferWithExtendableBuffer *const outBuffer) const;
 
-    void fillInHeader(const bool updatesLastUpdatedTime, const bool updatesLastDecayedTime,
+    void fillInHeader(const bool updatesLastDecayedTime,
             const int unigramCount, const int bigramCount, const int extendedRegionSize,
             HeaderReadWriteUtils::AttributeMap *outAttributeMap) const;
 
@@ -163,7 +163,7 @@
     static const char *const MULTIPLE_WORDS_DEMOTION_RATE_KEY;
     static const char *const REQUIRES_GERMAN_UMLAUT_PROCESSING_KEY;
     static const char *const IS_DECAYING_DICT_KEY;
-    static const char *const LAST_UPDATED_TIME_KEY;
+    static const char *const DATE_KEY;
     static const char *const LAST_DECAYED_TIME_KEY;
     static const char *const UNIGRAM_COUNT_KEY;
     static const char *const BIGRAM_COUNT_KEY;
@@ -179,7 +179,7 @@
     const float mMultiWordCostMultiplier;
     const bool mRequiresGermanUmlautProcessing;
     const bool mIsDecayingDict;
-    const int mLastUpdatedTime;
+    const int mDate;
     const int mLastDecayedTime;
     const int mUnigramCount;
     const int mBigramCount;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
index 2adafd2..67d615e 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
@@ -123,10 +123,10 @@
         }
     }
 
-    const UnigramProperty getUnigramProperty(const int *const codePoints,
+    const WordProperty getWordProperty(const int *const codePoints,
             const int codePointCount) const {
-        // getUnigramProperty is not supported.
-        return UnigramProperty();
+        // getWordProperty is not supported.
+        return WordProperty();
     }
 
  private:
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 b4730fe..0b067e1 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
@@ -20,7 +20,7 @@
 
 #include "suggest/core/dicnode/dic_node.h"
 #include "suggest/core/dicnode/dic_node_vector.h"
-#include "suggest/core/dictionary/unigram_property.h"
+#include "suggest/core/dictionary/word_property.h"
 #include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
 #include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
 #include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
@@ -317,15 +317,17 @@
     }
 }
 
-const UnigramProperty Ver4PatriciaTriePolicy::getUnigramProperty(const int *const codePoints,
+const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const codePoints,
         const int codePointCount) const {
     const int ptNodePos = getTerminalPtNodePositionOfWord(codePoints, codePointCount,
             false /* forceLowerCaseSearch */);
     if (ptNodePos == NOT_A_DICT_POS) {
-        AKLOGE("fetchUnigramProperty is called for invalid word.");
-        return UnigramProperty();
+        AKLOGE("getWordProperty is called for invalid word.");
+        return WordProperty();
     }
     const PtNodeParams ptNodeParams = mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos);
+    std::vector<int> codePointVector(ptNodeParams.getCodePoints(),
+            ptNodeParams.getCodePoints() + ptNodeParams.getCodePointCount());
     const ProbabilityEntry probabilityEntry =
             mBuffers.get()->getProbabilityDictContent()->getProbabilityEntry(
                     ptNodeParams.getTerminalId());
@@ -349,8 +351,8 @@
             shortcutProbabilities.push_back(shortcutProbability);
         }
     }
-    return UnigramProperty(ptNodeParams.getCodePoints(), ptNodeParams.getCodePointCount(),
-            ptNodeParams.isNotAWord(), ptNodeParams.isBlacklisted(), ptNodeParams.hasBigrams(),
+    return WordProperty(&codePointVector, ptNodeParams.isNotAWord(),
+            ptNodeParams.isBlacklisted(), ptNodeParams.hasBigrams(),
             ptNodeParams.hasShortcutTargets(), ptNodeParams.getProbability(),
             historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
             historicalInfo->getCount(), &shortcutTargets, &shortcutProbabilities);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
index 81aed20..a43bd0e 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
@@ -106,7 +106,7 @@
     void getProperty(const char *const query, const int queryLength, char *const outResult,
             const int maxResultLength);
 
-    const UnigramProperty getUnigramProperty(const int *const codePoints,
+    const WordProperty getWordProperty(const int *const codePoints,
             const int codePointCount) const;
 
  private:
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
index b6f813c..6720974 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
@@ -39,12 +39,11 @@
             BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
     const int extendedRegionSize = headerPolicy->getExtendedRegionSize()
             + mBuffers->getTrieBuffer()->getUsedAdditionalBufferSize();
-    if (!headerPolicy->fillInAndWriteHeaderToBuffer(false /* updatesLastUpdatedTime */,
-            false /* updatesLastDecayedTime */, unigramCount, bigramCount, extendedRegionSize,
-            &headerBuffer)) {
-        AKLOGE("Cannot write header structure to buffer. updatesLastUpdatedTime: %d, "
+    if (!headerPolicy->fillInAndWriteHeaderToBuffer(false /* updatesLastDecayedTime */,
+            unigramCount, bigramCount, extendedRegionSize, &headerBuffer)) {
+        AKLOGE("Cannot write header structure to buffer. "
                 "updatesLastDecayedTime: %d, unigramCount: %d, bigramCount: %d, "
-                "extendedRegionSize: %d", false, false, unigramCount, bigramCount,
+                "extendedRegionSize: %d", false, unigramCount, bigramCount,
                 extendedRegionSize);
         return;
     }
@@ -63,9 +62,8 @@
     }
     BufferWithExtendableBuffer headerBuffer(
             BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
-    if (!headerPolicy->fillInAndWriteHeaderToBuffer(true /* updatesLastUpdatedTime */,
-            true /* updatesLastDecayedTime */, unigramCount, bigramCount,
-            0 /* extendedRegionSize */, &headerBuffer)) {
+    if (!headerPolicy->fillInAndWriteHeaderToBuffer(true /* updatesLastDecayedTime */,
+            unigramCount, bigramCount, 0 /* extendedRegionSize */, &headerBuffer)) {
         return;
     }
     dictBuffers.get()->flushHeaderAndDictBuffers(dictDirPath, &headerBuffer);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
index 1e57a0b..84403c8 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
@@ -48,8 +48,8 @@
     HeaderPolicy headerPolicy(FormatUtils::VERSION_4, attributeMap);
     Ver4DictBuffers::Ver4DictBuffersPtr dictBuffers =
             Ver4DictBuffers::createVer4DictBuffers(&headerPolicy);
-    headerPolicy.fillInAndWriteHeaderToBuffer(true /* updatesLastUpdatedTime */,
-            true /* updatesLastDecayedTime */, 0 /* unigramCount */, 0 /* bigramCount */,
+    headerPolicy.fillInAndWriteHeaderToBuffer(true /* updatesLastDecayedTime */,
+            0 /* unigramCount */, 0 /* bigramCount */,
             0 /* extendedRegionSize */, dictBuffers.get()->getWritableHeaderBuffer());
     if (!DynamicPtWritingUtils::writeEmptyDictionary(
             dictBuffers.get()->getWritableTrieBuffer(), 0 /* rootPos */)) {
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
index 73b6fdc..844fcbb 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -26,7 +26,7 @@
 import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
 import com.android.inputmethod.latin.utils.FileUtils;
 import com.android.inputmethod.latin.utils.LanguageModelParam;
-import com.android.inputmethod.latin.utils.UnigramProperty;
+import com.android.inputmethod.latin.utils.WordProperty;
 
 import java.io.File;
 import java.io.IOException;
@@ -892,8 +892,7 @@
                 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
                 Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
 
-        final UnigramProperty invalidUnigramProperty =
-                binaryDictionary.getUnigramProperty("dummyWord");
+        final WordProperty invalidUnigramProperty = binaryDictionary.getWordProperty("dummyWord");
         assertFalse(invalidUnigramProperty.isValid());
 
         for (int i = 0; i < ITERATION_COUNT; i++) {
@@ -905,8 +904,7 @@
             binaryDictionary.addUnigramWord(word, unigramProbability,
                     null /* shortcutTarget */, BinaryDictionary.NOT_A_PROBABILITY,
                     isNotAWord, isBlacklisted, BinaryDictionary.NOT_A_VALID_TIMESTAMP);
-            final UnigramProperty unigramProperty =
-                    binaryDictionary.getUnigramProperty(word);
+            final WordProperty unigramProperty = binaryDictionary.getWordProperty(word);
             assertEquals(word, unigramProperty.mCodePoints);
             assertTrue(unigramProperty.isValid());
             assertEquals(isNotAWord, unigramProperty.mIsNotAWord);
@@ -938,7 +936,7 @@
         binaryDictionary.addUnigramWord("aaa", unigramProbability, "zzz",
                 shortcutProbability, false /* isNotAWord */, false /* isBlacklisted */,
                 0 /* timestamp */);
-        UnigramProperty unigramProperty = binaryDictionary.getUnigramProperty("aaa");
+        WordProperty unigramProperty = binaryDictionary.getWordProperty("aaa");
         assertEquals(1, unigramProperty.mShortcutTargets.size());
         assertEquals("zzz", unigramProperty.mShortcutTargets.get(0).mWord);
         assertEquals(shortcutProbability, unigramProperty.mShortcutTargets.get(0).mFrequency);
@@ -946,7 +944,7 @@
         binaryDictionary.addUnigramWord("aaa", unigramProbability, "zzz",
                 updatedShortcutProbability, false /* isNotAWord */, false /* isBlacklisted */,
                 0 /* timestamp */);
-        unigramProperty = binaryDictionary.getUnigramProperty("aaa");
+        unigramProperty = binaryDictionary.getWordProperty("aaa");
         assertEquals(1, unigramProperty.mShortcutTargets.size());
         assertEquals("zzz", unigramProperty.mShortcutTargets.get(0).mWord);
         assertEquals(updatedShortcutProbability,
@@ -957,7 +955,7 @@
         final HashMap<String, Integer> shortcutTargets = new HashMap<String, Integer>();
         shortcutTargets.put("zzz", updatedShortcutProbability);
         shortcutTargets.put("yyy", shortcutProbability);
-        unigramProperty = binaryDictionary.getUnigramProperty("aaa");
+        unigramProperty = binaryDictionary.getWordProperty("aaa");
         assertEquals(2, unigramProperty.mShortcutTargets.size());
         for (WeightedString shortcutTarget : unigramProperty.mShortcutTargets) {
             assertTrue(shortcutTargets.containsKey(shortcutTarget.mWord));
@@ -967,7 +965,7 @@
         shortcutTargets.put("zzz", updatedShortcutProbability);
         shortcutTargets.put("yyy", shortcutProbability);
         binaryDictionary.flushWithGC();
-        unigramProperty = binaryDictionary.getUnigramProperty("aaa");
+        unigramProperty = binaryDictionary.getWordProperty("aaa");
         assertEquals(2, unigramProperty.mShortcutTargets.size());
         for (WeightedString shortcutTarget : unigramProperty.mShortcutTargets) {
             assertTrue(shortcutTargets.containsKey(shortcutTarget.mWord));
@@ -1036,7 +1034,7 @@
         }
 
         for (final String word : words) {
-            final UnigramProperty unigramProperty = binaryDictionary.getUnigramProperty(word);
+            final WordProperty unigramProperty = binaryDictionary.getWordProperty(word);
             assertEquals((int)unigramProbabilities.get(word), unigramProperty.mProbability);
             if (!shortcutTargets.containsKey(word)) {
                 // The word does not have shortcut targets.