From 5bf1be71629607e7206e6203489cf742d2f8ed79 Mon Sep 17 00:00:00 2001
From: Keisuke Kuroynagi <ksk@google.com>
Date: Wed, 26 Jun 2013 12:51:33 +0900
Subject: [PATCH] Add jni methods for dynamically handling a dictionary.

Bug: 6669677
Change-Id: I8a26623adbb41a78e3c023c652be635c635e3b47
---
 .../inputmethod/latin/BinaryDictionary.java   |  6 +-
 ...oid_inputmethod_latin_BinaryDictionary.cpp | 80 ++++++++++++++++---
 .../core/dictionary/bigram_dictionary.cpp     |  8 +-
 .../suggest/core/dictionary/dictionary.cpp    | 33 +++++++-
 .../src/suggest/core/dictionary/dictionary.h  | 13 ++-
 5 files changed, 119 insertions(+), 21 deletions(-)

diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index f36c9e8785..c355fd60a5 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -97,7 +97,7 @@ public final class BinaryDictionary extends Dictionary {
             boolean isUpdatable);
     private static native void closeNative(long dict);
     private static native int getProbabilityNative(long dict, int[] word);
-    private static native boolean isValidBigramNative(long dict, int[] word1, int[] word2);
+    private static native boolean isValidBigramNative(long dict, int[] word0, int[] word1);
     private static native int getSuggestionsNative(long dict, long proximityInfo,
             long traverseSession, int[] xCoordinates, int[] yCoordinates, int[] times,
             int[] pointerIds, int[] inputCodePoints, int inputSize, int commitPoint,
@@ -105,6 +105,10 @@ public final class BinaryDictionary extends Dictionary {
             int[] outputCodePoints, int[] outputScores, int[] outputIndices, int[] outputTypes);
     private static native float calcNormalizedScoreNative(int[] before, int[] after, int score);
     private static native int editDistanceNative(int[] before, int[] after);
+    private static native void addUnigramWordNative(long dict, int[] word, int probability);
+    private static native void addBigramWordsNative(long dict, int[] word0, int[] word1,
+            int probability);
+    private static native void removeBigramWordsNative(long dict, int[] word0, int[] word1);
 
     // TODO: Move native dict into session
     private final void loadDictionary(final String path, final long startOffset,
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index b856718c6a..33b6a6f1b5 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -176,26 +176,26 @@ static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jclass clazz, j
 }
 
 static jint latinime_BinaryDictionary_getProbability(JNIEnv *env, jclass clazz, jlong dict,
-        jintArray wordArray) {
+        jintArray word) {
     Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) return 0;
-    const jsize codePointLength = env->GetArrayLength(wordArray);
-    int codePoints[codePointLength];
-    env->GetIntArrayRegion(wordArray, 0, codePointLength, codePoints);
-    return dictionary->getProbability(codePoints, codePointLength);
+    const jsize wordLength = env->GetArrayLength(word);
+    int codePoints[wordLength];
+    env->GetIntArrayRegion(word, 0, wordLength, codePoints);
+    return dictionary->getProbability(codePoints, wordLength);
 }
 
 static jboolean latinime_BinaryDictionary_isValidBigram(JNIEnv *env, jclass clazz, jlong dict,
-        jintArray wordArray1, jintArray wordArray2) {
+        jintArray word0, jintArray word1) {
     Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) return JNI_FALSE;
-    const jsize codePointLength1 = env->GetArrayLength(wordArray1);
-    const jsize codePointLength2 = env->GetArrayLength(wordArray2);
-    int codePoints1[codePointLength1];
-    int codePoints2[codePointLength2];
-    env->GetIntArrayRegion(wordArray1, 0, codePointLength1, codePoints1);
-    env->GetIntArrayRegion(wordArray2, 0, codePointLength2, codePoints2);
-    return dictionary->isValidBigram(codePoints1, codePointLength1, codePoints2, codePointLength2);
+    const jsize word0Length = env->GetArrayLength(word0);
+    const jsize word1Length = env->GetArrayLength(word1);
+    int word0CodePoints[word0Length];
+    int word1CodePoints[word1Length];
+    env->GetIntArrayRegion(word0, 0, word0Length, word0CodePoints);
+    env->GetIntArrayRegion(word1, 0, word1Length, word1CodePoints);
+    return dictionary->isValidBigram(word0CodePoints, word0Length, word1CodePoints, word1Length);
 }
 
 static jfloat latinime_BinaryDictionary_calcNormalizedScore(JNIEnv *env, jclass clazz,
@@ -246,6 +246,45 @@ static void releaseDictBuf(const void *dictBuf, const size_t length, const int f
     }
 }
 
+static void latinime_BinaryDictionary_addUnigramWord(JNIEnv *env, jclass clazz, jlong dict,
+        jintArray word, jint probability) {
+    Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
+    if (!dictionary) {
+        return;
+    }
+    jsize wordLength = env->GetArrayLength(word);
+    int codePoints[wordLength];
+    dictionary->addUnigramWord(codePoints, wordLength, probability);
+}
+
+static void latinime_BinaryDictionary_addBigramWords(JNIEnv *env, jclass clazz, jlong dict,
+        jintArray word0, jintArray word1, jint probability) {
+    Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
+    if (!dictionary) {
+        return;
+    }
+    jsize word0Length = env->GetArrayLength(word0);
+    int word0CodePoints[word0Length];
+    jsize word1Length = env->GetArrayLength(word1);
+    int word1CodePoints[word1Length];
+    dictionary->addBigramWords(word0CodePoints, word0Length, word1CodePoints,
+            word1Length, probability);
+}
+
+static void latinime_BinaryDictionary_removeBigramWords(JNIEnv *env, jclass clazz, jlong dict,
+        jintArray word0, jintArray word1) {
+    Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
+    if (!dictionary) {
+        return;
+    }
+    jsize word0Length = env->GetArrayLength(word0);
+    int word0CodePoints[word0Length];
+    jsize word1Length = env->GetArrayLength(word1);
+    int word1CodePoints[word1Length];
+    dictionary->removeBigramWords(word0CodePoints, word0Length, word1CodePoints,
+            word1Length);
+}
+
 static const JNINativeMethod sMethods[] = {
     {
         const_cast<char *>("openNative"),
@@ -281,6 +320,21 @@ static const JNINativeMethod sMethods[] = {
         const_cast<char *>("editDistanceNative"),
         const_cast<char *>("([I[I)I"),
         reinterpret_cast<void *>(latinime_BinaryDictionary_editDistance)
+    },
+    {
+        const_cast<char *>("addUnigramWordNative"),
+        const_cast<char *>("(J[II)V"),
+        reinterpret_cast<void *>(latinime_BinaryDictionary_addUnigramWord)
+    },
+    {
+        const_cast<char *>("addBigramWordsNative"),
+        const_cast<char *>("(J[I[II)V"),
+        reinterpret_cast<void *>(latinime_BinaryDictionary_addBigramWords)
+    },
+    {
+        const_cast<char *>("removeBigramWordsNative"),
+        const_cast<char *>("(J[I[I)V"),
+        reinterpret_cast<void *>(latinime_BinaryDictionary_removeBigramWords)
     }
 };
 
diff --git a/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp b/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp
index 6e02100fc3..242a9bdd6a 100644
--- a/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp
+++ b/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp
@@ -184,13 +184,13 @@ bool BigramDictionary::checkFirstCharacter(int *word, int *inputCodePoints) cons
     return false;
 }
 
-bool BigramDictionary::isValidBigram(const int *word1, int length1, const int *word2,
-        int length2) const {
-    int pos = getBigramListPositionForWord(word1, length1, false /* forceLowerCaseSearch */);
+bool BigramDictionary::isValidBigram(const int *word0, int length0, const int *word1,
+        int length1) const {
+    int pos = getBigramListPositionForWord(word0, length0, false /* forceLowerCaseSearch */);
     // getBigramListPositionForWord returns 0 if this word isn't in the dictionary or has no bigrams
     if (0 == pos) return false;
     int nextWordPos = BinaryFormat::getTerminalPosition(mBinaryDictionaryInfo->getDictRoot(),
-            word2, length2, false /* forceLowerCaseSearch */);
+            word1, length1, false /* forceLowerCaseSearch */);
     if (NOT_VALID_WORD == nextWordPos) return false;
 
     for (BinaryDictionaryBigramsIterator bigramsIt(mBinaryDictionaryInfo, pos);
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.cpp b/native/jni/src/suggest/core/dictionary/dictionary.cpp
index 028b61506a..51f23dc555 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.cpp
+++ b/native/jni/src/suggest/core/dictionary/dictionary.cpp
@@ -106,8 +106,37 @@ int Dictionary::getProbability(const int *word, int length) const {
     return unigramProbability;
 }
 
-bool Dictionary::isValidBigram(const int *word1, int length1, const int *word2, int length2) const {
-    return mBigramDictionary->isValidBigram(word1, length1, word2, length2);
+bool Dictionary::isValidBigram(const int *word0, int length0, const int *word1, int length1) const {
+    return mBigramDictionary->isValidBigram(word0, length0, word1, length1);
+}
+
+void Dictionary::addUnigramWord(const int *const word, const int length, const int probability) {
+    if (!mBinaryDictionaryInfo.isDynamicallyUpdatable()) {
+        // This method should not be called for non-updatable dictionary.
+        AKLOGI("Warning: Dictionary::addUnigramWord() is called for non-updatable dictionary.");
+        return;
+    }
+    // TODO: Support dynamic update
+}
+
+void Dictionary::addBigramWords(const int *const word0, const int length0, const int *const word1,
+        const int length1, const int probability) {
+    if (!mBinaryDictionaryInfo.isDynamicallyUpdatable()) {
+        // This method should not be called for non-updatable dictionary.
+        AKLOGI("Warning: Dictionary::addBigramWords() is called for non-updatable dictionary.");
+        return;
+    }
+    // TODO: Support dynamic update
+}
+
+void Dictionary::removeBigramWords(const int *const word0, const int length0,
+        const int *const word1, const int length1) {
+    if (!mBinaryDictionaryInfo.isDynamicallyUpdatable()) {
+        // This method should not be called for non-updatable dictionary.
+        AKLOGI("Warning: Dictionary::removeBigramWords() is called for non-updatable dictionary.");
+        return;
+    }
+    // TODO: Support dynamic update
 }
 
 } // namespace latinime
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.h b/native/jni/src/suggest/core/dictionary/dictionary.h
index afd0818414..94579c200f 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.h
+++ b/native/jni/src/suggest/core/dictionary/dictionary.h
@@ -64,10 +64,21 @@ class Dictionary {
             int *frequencies, int *outputTypes) const;
 
     int getProbability(const int *word, int length) const;
-    bool isValidBigram(const int *word1, int length1, const int *word2, int length2) const;
+
+    bool isValidBigram(const int *word0, int length0, const int *word1, int length1) const;
+
+    void addUnigramWord(const int *const word, const int length, const int probability);
+
+    void addBigramWords(const int *const word0, const int length0, const int *const word1,
+            const int length1, const int probability);
+
+    void removeBigramWords(const int *const word0, const int length0, const int *const word1,
+            const int length1);
+
     const BinaryDictionaryInfo *getBinaryDictionaryInfo() const {
         return &mBinaryDictionaryInfo;
     }
+
     virtual ~Dictionary();
 
  private:
-- 
GitLab