Extend jni method to dump ngram entries.

Bug: 14425059
Change-Id: Ib03b58525fae12f254b45630bee31ecbdde227b1
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 10dea74..afd423c 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -70,7 +70,7 @@
     private static final int FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT = 5;
     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_NGRAMS_INDEX = 2;
     private static final int FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX = 3;
     private static final int FORMAT_WORD_PROPERTY_IS_BEGINNING_OF_SENTENCE_INDEX = 4;
 
@@ -179,9 +179,10 @@
             boolean[] isBeginningOfSentenceArray, int[] word);
     private static native void getWordPropertyNative(long dict, int[] word,
             boolean isBeginningOfSentence, int[] outCodePoints, boolean[] outFlags,
-            int[] outProbabilityInfo, ArrayList<int[]> outBigramTargets,
-            ArrayList<int[]> outBigramProbabilityInfo, ArrayList<int[]> outShortcutTargets,
-            ArrayList<Integer> outShortcutProbabilities);
+            int[] outProbabilityInfo, ArrayList<int[][]> outNgramPrevWordsArray,
+            ArrayList<boolean[]> outNgramPrevWordIsBeginningOfSentenceArray,
+            ArrayList<int[]> outNgramTargets, ArrayList<int[]> outNgramProbabilityInfo,
+            ArrayList<int[]> outShortcutTargets, ArrayList<Integer> outShortcutProbabilities);
     private static native int getNextWordNative(long dict, int token, int[] outCodePoints,
             boolean[] outIsBeginningOfSentence);
     private static native void getSuggestionsNative(long dict, long proximityInfo,
@@ -388,20 +389,25 @@
         final boolean[] outFlags = new boolean[FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT];
         final int[] outProbabilityInfo =
                 new int[FORMAT_WORD_PROPERTY_OUTPUT_PROBABILITY_INFO_COUNT];
-        final ArrayList<int[]> outBigramTargets = new ArrayList<>();
-        final ArrayList<int[]> outBigramProbabilityInfo = new ArrayList<>();
+        final ArrayList<int[][]> outNgramPrevWordsArray = new ArrayList<>();
+        final ArrayList<boolean[]> outNgramPrevWordIsBeginningOfSentenceArray =
+                new ArrayList<>();
+        final ArrayList<int[]> outNgramTargets = new ArrayList<>();
+        final ArrayList<int[]> outNgramProbabilityInfo = new ArrayList<>();
         final ArrayList<int[]> outShortcutTargets = new ArrayList<>();
         final ArrayList<Integer> outShortcutProbabilities = new ArrayList<>();
         getWordPropertyNative(mNativeDict, codePoints, isBeginningOfSentence, outCodePoints,
-                outFlags, outProbabilityInfo, outBigramTargets, outBigramProbabilityInfo,
-                outShortcutTargets, outShortcutProbabilities);
+                outFlags, outProbabilityInfo, outNgramPrevWordsArray,
+                outNgramPrevWordIsBeginningOfSentenceArray, outNgramTargets,
+                outNgramProbabilityInfo, outShortcutTargets, outShortcutProbabilities);
         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_NGRAMS_INDEX],
                 outFlags[FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX],
                 outFlags[FORMAT_WORD_PROPERTY_IS_BEGINNING_OF_SENTENCE_INDEX], outProbabilityInfo,
-                outBigramTargets, outBigramProbabilityInfo, outShortcutTargets,
+                outNgramPrevWordsArray, outNgramPrevWordIsBeginningOfSentenceArray,
+                outNgramTargets, outNgramProbabilityInfo, outShortcutTargets,
                 outShortcutProbabilities);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
index a180d06..1e6cadf 100644
--- a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
+++ b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
@@ -26,6 +26,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 
+import javax.annotation.Nullable;
+
 /**
  * Utility class for a word with a probability.
  *
@@ -49,7 +51,7 @@
     @UsedForTesting
     public WordProperty(final String word, final ProbabilityInfo probabilityInfo,
             final ArrayList<WeightedString> shortcutTargets,
-            final ArrayList<WeightedString> bigrams,
+            @Nullable final ArrayList<WeightedString> bigrams,
             final boolean isNotAWord, final boolean isBlacklistEntry) {
         mWord = word;
         mProbabilityInfo = probabilityInfo;
@@ -85,7 +87,9 @@
     public WordProperty(final int[] codePoints, final boolean isNotAWord,
             final boolean isBlacklisted, final boolean hasBigram, final boolean hasShortcuts,
             final boolean isBeginningOfSentence, final int[] probabilityInfo,
-            final ArrayList<int[]> bigramTargets, final ArrayList<int[]> bigramProbabilityInfo,
+            final ArrayList<int[][]> ngramPrevWordsArray,
+            final ArrayList<boolean[]> outNgramPrevWordIsBeginningOfSentenceArray,
+            final ArrayList<int[]> ngramTargets, final ArrayList<int[]> ngramProbabilityInfo,
             final ArrayList<int[]> shortcutTargets,
             final ArrayList<Integer> shortcutProbabilities) {
         mWord = StringUtils.getStringFromNullTerminatedCodePointArray(codePoints);
@@ -98,15 +102,15 @@
         mHasShortcuts = hasShortcuts;
         mHasNgrams = hasBigram;
 
-        final int relatedNgramCount = bigramTargets.size();
+        final int relatedNgramCount = ngramTargets.size();
         final WordInfo currentWordInfo =
                 mIsBeginningOfSentence ? WordInfo.BEGINNING_OF_SENTENCE : new WordInfo(mWord);
         final NgramContext ngramContext = new NgramContext(currentWordInfo);
         for (int i = 0; i < relatedNgramCount; i++) {
             final String ngramTargetString =
-                    StringUtils.getStringFromNullTerminatedCodePointArray(bigramTargets.get(i));
+                    StringUtils.getStringFromNullTerminatedCodePointArray(ngramTargets.get(i));
             final WeightedString ngramTarget = new WeightedString(ngramTargetString,
-                    createProbabilityInfoFromArray(bigramProbabilityInfo.get(i)));
+                    createProbabilityInfoFromArray(ngramProbabilityInfo.get(i)));
             // TODO: Support n-gram.
             ngrams.add(new NgramProperty(ngramTarget, ngramContext));
         }
@@ -180,7 +184,8 @@
                 && mHasNgrams == w.mHasNgrams && mHasShortcuts && w.mHasNgrams;
     }
 
-    private <T> boolean equals(final ArrayList<T> a, final ArrayList<T> b) {
+    // TDOO: Have a utility method like java.util.Objects.equals.
+    private static <T> boolean equals(final ArrayList<T> a, final ArrayList<T> b) {
         if (null == a) {
             return null == b;
         }
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 76c7fdd..b54aca6 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -327,8 +327,9 @@
 
 static void latinime_BinaryDictionary_getWordProperty(JNIEnv *env, jclass clazz,
         jlong dict, jintArray word, jboolean isBeginningOfSentence, jintArray outCodePoints,
-        jbooleanArray outFlags, jintArray outProbabilityInfo, jobject outBigramTargets,
-        jobject outBigramProbabilityInfo, jobject outShortcutTargets,
+        jbooleanArray outFlags, jintArray outProbabilityInfo, jobject /* outNgramPrevWordsArray */,
+        jobject /* outNgramPrevWordIsBeginningOfSentenceArray */, jobject outNgramTargets,
+        jobject outNgramProbabilityInfo, jobject outShortcutTargets,
         jobject outShortcutProbabilities) {
     Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) return;
@@ -351,7 +352,7 @@
     const WordProperty wordProperty = dictionary->getWordProperty(
             CodePointArrayView(wordCodePoints, codePointCount));
     wordProperty.outputProperties(env, outCodePoints, outFlags, outProbabilityInfo,
-            outBigramTargets, outBigramProbabilityInfo, outShortcutTargets,
+            outNgramTargets, outNgramProbabilityInfo, outShortcutTargets,
             outShortcutProbabilities);
 }
 
@@ -718,7 +719,8 @@
     {
         const_cast<char *>("getWordPropertyNative"),
         const_cast<char *>("(J[IZ[I[Z[ILjava/util/ArrayList;Ljava/util/ArrayList;"
-                "Ljava/util/ArrayList;Ljava/util/ArrayList;)V"),
+                "Ljava/util/ArrayList;Ljava/util/ArrayList;Ljava/util/ArrayList;"
+                "Ljava/util/ArrayList;)V"),
         reinterpret_cast<void *>(latinime_BinaryDictionary_getWordProperty)
     },
     {