NgramContext.java revision bbd6a26be025bc419e342e32d86629c4ebd68dd8
183c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi/* 283c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi * Copyright (C) 2014 The Android Open Source Project 383c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi * 483c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi * Licensed under the Apache License, Version 2.0 (the "License"); 583c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi * you may not use this file except in compliance with the License. 683c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi * You may obtain a copy of the License at 783c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi * 883c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi * http://www.apache.org/licenses/LICENSE-2.0 983c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi * 1083c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi * Unless required by applicable law or agreed to in writing, software 1183c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi * distributed under the License is distributed on an "AS IS" BASIS, 1283c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1383c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi * See the License for the specific language governing permissions and 1483c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi * limitations under the License. 1583c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi */ 1683c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi 1783c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagipackage com.android.inputmethod.latin; 1883c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi 1986f36003fd4397143bd37938dda029e5707634afYohei Yukawaimport android.text.TextUtils; 20e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi 21bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagiimport com.android.inputmethod.annotations.UsedForTesting; 22e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagiimport com.android.inputmethod.latin.utils.StringUtils; 23e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi 2486f36003fd4397143bd37938dda029e5707634afYohei Yukawaimport java.util.Arrays; 2586f36003fd4397143bd37938dda029e5707634afYohei Yukawa 26a790c5b68324da41428aeb68594d43ca5632f66dKeisuke Kuroyanagi/** 27a790c5b68324da41428aeb68594d43ca5632f66dKeisuke Kuroyanagi * Class to represent information of previous words. This class is used to add n-gram entries 28a790c5b68324da41428aeb68594d43ca5632f66dKeisuke Kuroyanagi * into binary dictionaries, to get predictions, and to get suggestions. 29a790c5b68324da41428aeb68594d43ca5632f66dKeisuke Kuroyanagi */ 3083c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagipublic class PrevWordsInfo { 31e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi public static final PrevWordsInfo EMPTY_PREV_WORDS_INFO = 32e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi new PrevWordsInfo(WordInfo.EMPTY_WORD_INFO); 331c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi public static final PrevWordsInfo BEGINNING_OF_SENTENCE = 341c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi new PrevWordsInfo(WordInfo.BEGINNING_OF_SENTENCE); 351adca93381d261a6070be2721dbf8b8abafbfe01Keisuke Kuroyanagi 36e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi /** 37e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi * Word information used to represent previous words information. 38e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi */ 39e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi public static class WordInfo { 40e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi public static final WordInfo EMPTY_WORD_INFO = new WordInfo(null); 41e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi public static final WordInfo BEGINNING_OF_SENTENCE = new WordInfo(); 42e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi 4386f36003fd4397143bd37938dda029e5707634afYohei Yukawa // This is an empty char sequence when mIsBeginningOfSentence is true. 4486f36003fd4397143bd37938dda029e5707634afYohei Yukawa public final CharSequence mWord; 45e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi // TODO: Have sentence separator. 46e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi // Whether the current context is beginning of sentence or not. This is true when composing 47e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi // at the beginning of an input field or composing a word after a sentence separator. 48e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi public final boolean mIsBeginningOfSentence; 49e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi 50e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi // Beginning of sentence. 51e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi public WordInfo() { 52e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi mWord = ""; 53e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi mIsBeginningOfSentence = true; 54e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi } 55e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi 5686f36003fd4397143bd37938dda029e5707634afYohei Yukawa public WordInfo(final CharSequence word) { 57e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi mWord = word; 58e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi mIsBeginningOfSentence = false; 59e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi } 60e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi 61e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi public boolean isValid() { 62e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi return mWord != null; 63e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi } 641c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi 651c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi @Override 661c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi public int hashCode() { 671c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi return Arrays.hashCode(new Object[] { mWord, mIsBeginningOfSentence } ); 681c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi } 691c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi 701c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi @Override 711c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi public boolean equals(Object o) { 721c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi if (this == o) return true; 731c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi if (!(o instanceof WordInfo)) return false; 741c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi final WordInfo wordInfo = (WordInfo)o; 751c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi if (mWord == null || wordInfo.mWord == null) { 761c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi return mWord == wordInfo.mWord 771c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi && mIsBeginningOfSentence == wordInfo.mIsBeginningOfSentence; 781c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi } 7986f36003fd4397143bd37938dda029e5707634afYohei Yukawa return TextUtils.equals(mWord, wordInfo.mWord) 801c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi && mIsBeginningOfSentence == wordInfo.mIsBeginningOfSentence; 811c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi } 82e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi } 8383c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi 84e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi // The words immediately before the considered word. EMPTY_WORD_INFO element means we don't 85e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi // have any context for that previous word including the "beginning of sentence context" - we 86e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi // just don't know what to predict using the information. An example of that is after a comma. 87e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi // For simplicity of implementation, elements may also be EMPTY_WORD_INFO transiently after the 88e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi // WordComposer was reset and before starting a new composing word, but we should never be 89e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi // calling getSuggetions* in this situation. 90bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi private final WordInfo[] mPrevWordsInfo; 91bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi private final int mPrevWordsCount; 9217f326b7458c2bde2569e283a96e703755485328Keisuke Kuroyanagi 93e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi // Construct from the previous word information. 94bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi public PrevWordsInfo(final WordInfo... prevWordsInfo) { 95bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi mPrevWordsInfo = prevWordsInfo; 96bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi mPrevWordsCount = prevWordsInfo.length; 97e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi } 98e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi 99bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi // Construct from WordInfo array and size. The caller shouldn't change prevWordsInfo after 100bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi // calling this method. 101bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi private PrevWordsInfo(final PrevWordsInfo prevWordsInfo, final int prevWordsCount) { 102bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi if (prevWordsInfo.mPrevWordsCount < prevWordsCount) { 103bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi throw new IndexOutOfBoundsException("prevWordsInfo.mPrevWordsCount (" 104bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi + prevWordsInfo.mPrevWordsCount + ") is smaller than prevWordsCount (" 105bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi + prevWordsCount + ")"); 106bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi } 107bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi mPrevWordsInfo = prevWordsInfo.mPrevWordsInfo; 108bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi mPrevWordsCount = prevWordsCount; 109e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi } 110e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi 111e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi // Create next prevWordsInfo using current prevWordsInfo. 112e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi public PrevWordsInfo getNextPrevWordsInfo(final WordInfo wordInfo) { 1134466464c24d6c6523f170f56b7e65e43ceb699e2Keisuke Kuroyanagi final int nextPrevWordCount = Math.min(Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM, 114bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi mPrevWordsCount + 1); 1154466464c24d6c6523f170f56b7e65e43ceb699e2Keisuke Kuroyanagi final WordInfo[] prevWordsInfo = new WordInfo[nextPrevWordCount]; 116e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi prevWordsInfo[0] = wordInfo; 117bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi System.arraycopy(mPrevWordsInfo, 0, prevWordsInfo, 1, nextPrevWordCount - 1); 118e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi return new PrevWordsInfo(prevWordsInfo); 11983c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi } 1201adca93381d261a6070be2721dbf8b8abafbfe01Keisuke Kuroyanagi 1211adca93381d261a6070be2721dbf8b8abafbfe01Keisuke Kuroyanagi public boolean isValid() { 122bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi return mPrevWordsCount > 0 && mPrevWordsInfo[0].isValid(); 123bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi } 124bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi 125bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi public boolean isBeginningOfSentenceContext() { 126bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi return mPrevWordsCount > 0 && mPrevWordsInfo[0].mIsBeginningOfSentence; 127bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi } 128bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi 129bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi // n is 1-indexed. 130bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi // TODO: Remove 131bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi public CharSequence getNthPrevWord(final int n) { 132bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi if (n <= 0 || n > mPrevWordsCount) { 133bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi return null; 134bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi } 135bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi return mPrevWordsInfo[n - 1].mWord; 136bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi } 137bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi 138bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi // n is 1-indexed. 139bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi @UsedForTesting 140bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi public boolean isNthPrevWordBeginningOfSontence(final int n) { 141bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi if (n <= 0 || n > mPrevWordsCount) { 142bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi return false; 143bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi } 144bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi return mPrevWordsInfo[n - 1].mIsBeginningOfSentence; 145e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi } 146e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi 147e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi public void outputToArray(final int[][] codePointArrays, 148e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi final boolean[] isBeginningOfSentenceArray) { 149bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi for (int i = 0; i < mPrevWordsCount; i++) { 150e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi final WordInfo wordInfo = mPrevWordsInfo[i]; 151e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi if (wordInfo == null || !wordInfo.isValid()) { 152e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi codePointArrays[i] = new int[0]; 153e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi isBeginningOfSentenceArray[i] = false; 154e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi continue; 155e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi } 156e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi codePointArrays[i] = StringUtils.toCodePointArray(wordInfo.mWord); 157e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi isBeginningOfSentenceArray[i] = wordInfo.mIsBeginningOfSentence; 158e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi } 1591adca93381d261a6070be2721dbf8b8abafbfe01Keisuke Kuroyanagi } 160dfca51726e9dc9a35f462dee39331823eafa07c9Keisuke Kuroyanagi 161ddfaeff544c77b1d42857ebf34ca2545e8868e13Keisuke Kuroyanagi public PrevWordsInfo getTrimmedPrevWordsInfo(final int maxPrevWordCount) { 162bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi final int newSize = Math.min(maxPrevWordCount, mPrevWordsCount); 163bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi return new PrevWordsInfo(this /* prevWordsInfo */, newSize); 164ddfaeff544c77b1d42857ebf34ca2545e8868e13Keisuke Kuroyanagi } 165ddfaeff544c77b1d42857ebf34ca2545e8868e13Keisuke Kuroyanagi 1664466464c24d6c6523f170f56b7e65e43ceb699e2Keisuke Kuroyanagi public int getPrevWordCount() { 167bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi return mPrevWordsCount; 1684466464c24d6c6523f170f56b7e65e43ceb699e2Keisuke Kuroyanagi } 1694466464c24d6c6523f170f56b7e65e43ceb699e2Keisuke Kuroyanagi 170dfca51726e9dc9a35f462dee39331823eafa07c9Keisuke Kuroyanagi @Override 1711c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi public int hashCode() { 172845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi // Just for having equals(). 173845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi return mPrevWordsInfo[0].hashCode(); 1741c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi } 1751c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi 1761c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi @Override 1771c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi public boolean equals(Object o) { 1781c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi if (this == o) return true; 1791c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi if (!(o instanceof PrevWordsInfo)) return false; 1801c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi final PrevWordsInfo prevWordsInfo = (PrevWordsInfo)o; 181845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi 182bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi final int minLength = Math.min(mPrevWordsCount, prevWordsInfo.mPrevWordsCount); 183845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi for (int i = 0; i < minLength; i++) { 184845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi if (!mPrevWordsInfo[i].equals(prevWordsInfo.mPrevWordsInfo[i])) { 185845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi return false; 186845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi } 187845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi } 188bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi final WordInfo[] longerWordsInfo; 189bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi final int longerWordsInfoCount; 190bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi if (mPrevWordsCount > prevWordsInfo.mPrevWordsCount) { 191bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi longerWordsInfo = mPrevWordsInfo; 192bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi longerWordsInfoCount = mPrevWordsCount; 193bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi } else { 194bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi longerWordsInfo = prevWordsInfo.mPrevWordsInfo; 195bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi longerWordsInfoCount = prevWordsInfo.mPrevWordsCount; 196bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi } 197bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi for (int i = minLength; i < longerWordsInfoCount; i++) { 198845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi if (longerWordsInfo[i] != null 199845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi && !WordInfo.EMPTY_WORD_INFO.equals(longerWordsInfo[i])) { 200845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi return false; 201845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi } 202845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi } 203845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi return true; 2041c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi } 2051c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi 2061c2f1ada8305e36defa8572da687a4596bf083eaKeisuke Kuroyanagi @Override 207dfca51726e9dc9a35f462dee39331823eafa07c9Keisuke Kuroyanagi public String toString() { 208e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi final StringBuffer builder = new StringBuffer(); 209bbd6a26be025bc419e342e32d86629c4ebd68dd8Keisuke Kuroyanagi for (int i = 0; i < mPrevWordsCount; i++) { 210e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi final WordInfo wordInfo = mPrevWordsInfo[i]; 211e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi builder.append("PrevWord["); 212e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi builder.append(i); 213e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi builder.append("]: "); 214845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi if (wordInfo == null) { 215845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi builder.append("null. "); 216845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi continue; 217845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi } 218845c061970f0dcbe75eac028e142aa054f88e2a9Keisuke Kuroyanagi if (!wordInfo.isValid()) { 219e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi builder.append("Empty. "); 220e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi continue; 221e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi } 222e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi builder.append(wordInfo.mWord); 223e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi builder.append(", isBeginningOfSentence: "); 224e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi builder.append(wordInfo.mIsBeginningOfSentence); 225e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi builder.append(". "); 226e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi } 227e708b1bc2e11285ad404133b8de21719ce08acb5Keisuke Kuroyanagi return builder.toString(); 228dfca51726e9dc9a35f462dee39331823eafa07c9Keisuke Kuroyanagi } 22983c40a2301a0b5a42a75eecada48e7887a7c940eKeisuke Kuroyanagi} 230