Make SuggestedWords immutable completely

Change-Id: I1b0f7b857e89307c987187c1969a2846aa97fdcc
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index f2ba7e0..64b9f33 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1827,9 +1827,8 @@
                 builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions);
             }
         }
-        final SuggestedWords suggestedWords = builder.build();
-        if (Utils.shouldBlockAutoCorrectionBySafetyNet(suggestedWords, mSuggest)) {
-            suggestedWords.setShouldBlockAutoCorrectionBySafetyNet();
+        if (Utils.shouldBlockAutoCorrectionBySafetyNet(builder, mSuggest)) {
+            builder.setShouldBlockAutoCorrectionBySafetyNet();
         }
         showSuggestions(builder.build(), typedWord);
     }
@@ -1837,7 +1836,7 @@
     public void showSuggestions(final SuggestedWords suggestedWords, final CharSequence typedWord) {
         final CharSequence autoCorrection;
         if (suggestedWords.size() > 0) {
-            if (!suggestedWords.shouldBlockAutoCorrectionBySafetyNet()
+            if (!suggestedWords.mShouldBlockAutoCorrectionBySafetyNet
                     && suggestedWords.hasAutoCorrectionWord()) {
                 autoCorrection = suggestedWords.getWord(1);
             } else {
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 9383c89..aad975e 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -26,18 +26,19 @@
 import java.util.List;
 
 public class SuggestedWords {
-    public static final SuggestedWords EMPTY = new SuggestedWords(null, false, false, false, null);
+    public static final SuggestedWords EMPTY = new SuggestedWords(null, false, false, false, false,
+            null);
 
     private final List<CharSequence> mWords;
     public final boolean mTypedWordValid;
     public final boolean mHasAutoCorrectionCandidate;
     public final boolean mIsPunctuationSuggestions;
+    public final boolean mShouldBlockAutoCorrectionBySafetyNet;
     private final List<SuggestedWordInfo> mSuggestedWordInfoList;
-    // TODO: Make the following member final.
-    private boolean mShouldBlockAutoCorrectionBySafetyNet;
 
     SuggestedWords(List<CharSequence> words, boolean typedWordValid,
             boolean hasAutoCorrectionCandidate, boolean isPunctuationSuggestions,
+            boolean shouldBlockAutoCorrectionBySafetyNet,
             List<SuggestedWordInfo> suggestedWordInfoList) {
         if (words != null) {
             mWords = words;
@@ -47,8 +48,8 @@
         mTypedWordValid = typedWordValid;
         mHasAutoCorrectionCandidate = hasAutoCorrectionCandidate;
         mIsPunctuationSuggestions = isPunctuationSuggestions;
+        mShouldBlockAutoCorrectionBySafetyNet = shouldBlockAutoCorrectionBySafetyNet;
         mSuggestedWordInfoList = suggestedWordInfoList;
-        mShouldBlockAutoCorrectionBySafetyNet = false;
     }
 
     public int size() {
@@ -67,18 +68,20 @@
         return mHasAutoCorrectionCandidate && size() > 1 && !mTypedWordValid;
     }
 
-    // TODO: Remove this method.
-    public void setShouldBlockAutoCorrectionBySafetyNet() {
-        mShouldBlockAutoCorrectionBySafetyNet = true;
-    }
-
-    public boolean shouldBlockAutoCorrectionBySafetyNet() {
-        return mShouldBlockAutoCorrectionBySafetyNet;
-    }
-
     public boolean willAutoCorrect() {
         return !mTypedWordValid && mHasAutoCorrectionCandidate
-                && !shouldBlockAutoCorrectionBySafetyNet();
+                && !mShouldBlockAutoCorrectionBySafetyNet;
+    }
+
+    @Override
+    public String toString() {
+        // Pretty-print method to help debug
+        return "SuggestedWords:"
+                + " mTypedWordValid=" + mTypedWordValid
+                + " mHasAutoCorrectionCandidate=" + mHasAutoCorrectionCandidate
+                + " mIsPunctuationSuggestions=" + mIsPunctuationSuggestions
+                + " mShouldBlockAutoCorrectionBySafetyNet=" + mShouldBlockAutoCorrectionBySafetyNet
+                + " mWords=" + Arrays.toString(mWords.toArray());
     }
 
     public static class Builder {
@@ -86,6 +89,7 @@
         private boolean mTypedWordValid;
         private boolean mHasMinimalSuggestion;
         private boolean mIsPunctuationSuggestions;
+        private boolean mShouldBlockAutoCorrectionBySafetyNet;
         private List<SuggestedWordInfo> mSuggestedWordInfoList =
                 new ArrayList<SuggestedWordInfo>();
 
@@ -150,6 +154,11 @@
             return this;
         }
 
+        public Builder setShouldBlockAutoCorrectionBySafetyNet() {
+            mShouldBlockAutoCorrectionBySafetyNet = true;
+            return this;
+        }
+
         // Should get rid of the first one (what the user typed previously) from suggestions
         // and replace it with what the user currently typed.
         public Builder addTypedWordAndPreviousSuggestions(CharSequence typedWord,
@@ -175,7 +184,8 @@
 
         public SuggestedWords build() {
             return new SuggestedWords(mWords, mTypedWordValid, mHasMinimalSuggestion,
-                    mIsPunctuationSuggestions, mSuggestedWordInfoList);
+                    mIsPunctuationSuggestions, mShouldBlockAutoCorrectionBySafetyNet,
+                    mSuggestedWordInfoList);
         }
 
         public int size() {
@@ -186,13 +196,19 @@
             return mWords.get(pos);
         }
 
+        public boolean isTypedWordValid() {
+            return mTypedWordValid;
+        }
+
         @Override
         public String toString() {
             // Pretty-print method to help debug
             return "SuggestedWords.Builder:"
-                    + " mTypedWordValid = " + mTypedWordValid
-                    + " mHasMinimalSuggestion = " + mHasMinimalSuggestion
-                    + " mIsPunctuationSuggestions = " + mIsPunctuationSuggestions
+                    + " mTypedWordValid=" + mTypedWordValid
+                    + " mHasMinimalSuggestion=" + mHasMinimalSuggestion
+                    + " mIsPunctuationSuggestions=" + mIsPunctuationSuggestions
+                    + " mShouldBlockAutoCorrectionBySafetyNet="
+                    + mShouldBlockAutoCorrectionBySafetyNet
                     + " mWords=" + Arrays.toString(mWords.toArray());
         }
     }
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index f6bc854..33d4b87 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -190,19 +190,25 @@
 
     // TODO: Resolve the inconsistencies between the native auto correction algorithms and
     // this safety net
-    public static boolean shouldBlockAutoCorrectionBySafetyNet(SuggestedWords suggestions,
-            Suggest suggest) {
+    public static boolean shouldBlockAutoCorrectionBySafetyNet(
+            SuggestedWords.Builder suggestedWordsBuilder, Suggest suggest) {
         // Safety net for auto correction.
         // Actually if we hit this safety net, it's actually a bug.
-        if (suggestions.size() <= 1 || suggestions.mTypedWordValid) return false;
+        if (suggestedWordsBuilder.size() <= 1 || suggestedWordsBuilder.isTypedWordValid()) {
+            return false;
+        }
         // If user selected aggressive auto correction mode, there is no need to use the safety
         // net.
-        if (suggest.isAggressiveAutoCorrectionMode()) return false;
-        final CharSequence typedWord = suggestions.getWord(0);
+        if (suggest.isAggressiveAutoCorrectionMode()) {
+            return false;
+        }
+        final CharSequence typedWord = suggestedWordsBuilder.getWord(0);
         // If the length of typed word is less than MINIMUM_SAFETY_NET_CHAR_LENGTH,
         // we should not use net because relatively edit distance can be big.
-        if (typedWord.length() < MINIMUM_SAFETY_NET_CHAR_LENGTH) return false;
-        final CharSequence suggestionWord = suggestions.getWord(1);
+        if (typedWord.length() < MINIMUM_SAFETY_NET_CHAR_LENGTH) {
+            return false;
+        }
+        final CharSequence suggestionWord = suggestedWordsBuilder.getWord(1);
         final int typedWordLength = typedWord.length();
         final int maxEditDistanceOfNativeDictionary =
                 (typedWordLength < 5 ? 2 : typedWordLength / 2) + 1;
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
index 31c32bd..d336294 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
@@ -94,7 +94,7 @@
     private final TextView mPreviewText;
 
     private Listener mListener;
-    private SuggestedWords mSuggestions = SuggestedWords.EMPTY;
+    private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
 
     private final SuggestionsViewParams mParams;
     private static final float MIN_TEXT_XSCALE = 0.70f;
@@ -258,10 +258,10 @@
             return a.getFraction(index, 1000, 1000, 1) / 1000.0f;
         }
 
-        private CharSequence getStyledSuggestionWord(SuggestedWords suggestions, int pos) {
-            final CharSequence word = suggestions.getWord(pos);
-            final boolean isAutoCorrect = pos == 1 && suggestions.willAutoCorrect();
-            final boolean isTypedWordValid = pos == 0 && suggestions.mTypedWordValid;
+        private CharSequence getStyledSuggestionWord(SuggestedWords suggestedWords, int pos) {
+            final CharSequence word = suggestedWords.getWord(pos);
+            final boolean isAutoCorrect = pos == 1 && suggestedWords.willAutoCorrect();
+            final boolean isTypedWordValid = pos == 0 && suggestedWords.mTypedWordValid;
             if (!isAutoCorrect && !isTypedWordValid)
                 return word;
 
@@ -278,10 +278,10 @@
             return spannedWord;
         }
 
-        private int getWordPosition(int index, SuggestedWords suggestions) {
+        private int getWordPosition(int index, SuggestedWords suggestedWords) {
             // TODO: This works for 3 suggestions. Revisit this algorithm when there are 5 or more
             // suggestions.
-            final int centerPos = suggestions.willAutoCorrect() ? 1 : 0;
+            final int centerPos = suggestedWords.willAutoCorrect() ? 1 : 0;
             if (index == mCenterSuggestionIndex) {
                 return centerPos;
             } else if (index == centerPos) {
@@ -291,14 +291,14 @@
             }
         }
 
-        private int getSuggestionTextColor(int index, SuggestedWords suggestions, int pos) {
+        private int getSuggestionTextColor(int index, SuggestedWords suggestedWords, int pos) {
             // TODO: Need to revisit this logic with bigram suggestions
             final boolean isSuggested = (pos != 0);
 
             final int color;
-            if (index == mCenterSuggestionIndex && suggestions.willAutoCorrect()) {
+            if (index == mCenterSuggestionIndex && suggestedWords.willAutoCorrect()) {
                 color = mColorAutoCorrect;
-            } else if (index == mCenterSuggestionIndex && suggestions.mTypedWordValid) {
+            } else if (index == mCenterSuggestionIndex && suggestedWords.mTypedWordValid) {
                 color = mColorValidTypedWord;
             } else if (isSuggested) {
                 color = mColorSuggested;
@@ -306,14 +306,14 @@
                 color = mColorTypedWord;
             }
             if (LatinImeLogger.sDBG) {
-                if (index == mCenterSuggestionIndex && suggestions.mHasAutoCorrectionCandidate
-                        && suggestions.shouldBlockAutoCorrectionBySafetyNet()) {
+                if (index == mCenterSuggestionIndex && suggestedWords.mHasAutoCorrectionCandidate
+                        && suggestedWords.mShouldBlockAutoCorrectionBySafetyNet) {
                     return 0xFFFF0000;
                 }
             }
 
-            final SuggestedWordInfo info = (pos < suggestions.size())
-                    ? suggestions.getInfo(pos) : null;
+            final SuggestedWordInfo info = (pos < suggestedWords.size())
+                    ? suggestedWords.getInfo(pos) : null;
             if (info != null && info.isObsoleteSuggestedWord()) {
                 return applyAlpha(color, mAlphaObsoleted);
             } else {
@@ -333,19 +333,19 @@
             params.gravity = Gravity.CENTER;
         }
 
-        public void layout(SuggestedWords suggestions, ViewGroup stripView, ViewGroup placer,
+        public void layout(SuggestedWords suggestedWords, ViewGroup stripView, ViewGroup placer,
                 int stripWidth) {
-            if (suggestions.mIsPunctuationSuggestions) {
-                layoutPunctuationSuggestions(suggestions, stripView);
+            if (suggestedWords.mIsPunctuationSuggestions) {
+                layoutPunctuationSuggestions(suggestedWords, stripView);
                 return;
             }
 
             final int countInStrip = mSuggestionsCountInStrip;
-            setupTexts(suggestions, countInStrip);
-            mMoreSuggestionsAvailable = (suggestions.size() > countInStrip);
+            setupTexts(suggestedWords, countInStrip);
+            mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip);
             int x = 0;
             for (int index = 0; index < countInStrip; index++) {
-                final int pos = getWordPosition(index, suggestions);
+                final int pos = getWordPosition(index, suggestedWords);
 
                 if (index != 0) {
                     final View divider = mDividers.get(pos);
@@ -368,7 +368,7 @@
 
                 // Disable this suggestion if the suggestion is null or empty.
                 word.setEnabled(!TextUtils.isEmpty(styled));
-                word.setTextColor(getSuggestionTextColor(index, suggestions, pos));
+                word.setTextColor(getSuggestionTextColor(index, suggestedWords, pos));
                 final int width = getSuggestionWidth(index, stripWidth);
                 final CharSequence text = getEllipsizedText(styled, width, word.getPaint());
                 final float scaleX = word.getTextScaleX();
@@ -380,7 +380,7 @@
                 x += word.getMeasuredWidth();
 
                 if (DBG) {
-                    final CharSequence debugInfo = getDebugInfo(suggestions, pos);
+                    final CharSequence debugInfo = getDebugInfo(suggestedWords, pos);
                     if (debugInfo != null) {
                         final TextView info = mInfos.get(pos);
                         info.setText(debugInfo);
@@ -412,11 +412,11 @@
             }
         }
 
-        private void setupTexts(SuggestedWords suggestions, int countInStrip) {
+        private void setupTexts(SuggestedWords suggestedWords, int countInStrip) {
             mTexts.clear();
-            final int count = Math.min(suggestions.size(), countInStrip);
+            final int count = Math.min(suggestedWords.size(), countInStrip);
             for (int pos = 0; pos < count; pos++) {
-                final CharSequence styled = getStyledSuggestionWord(suggestions, pos);
+                final CharSequence styled = getStyledSuggestionWord(suggestedWords, pos);
                 mTexts.add(styled);
             }
             for (int pos = count; pos < countInStrip; pos++) {
@@ -425,8 +425,9 @@
             }
         }
 
-        private void layoutPunctuationSuggestions(SuggestedWords suggestions, ViewGroup stripView) {
-            final int countInStrip = Math.min(suggestions.size(), PUNCTUATIONS_IN_STRIP);
+        private void layoutPunctuationSuggestions(SuggestedWords suggestedWords,
+                ViewGroup stripView) {
+            final int countInStrip = Math.min(suggestedWords.size(), PUNCTUATIONS_IN_STRIP);
             for (int index = 0; index < countInStrip; index++) {
                 if (index != 0) {
                     // Add divider if this isn't the left most suggestion in suggestions strip.
@@ -436,7 +437,7 @@
                 final TextView word = mWords.get(index);
                 word.setEnabled(true);
                 word.setTextColor(mColorAutoCorrect);
-                final CharSequence text = suggestions.getWord(index);
+                final CharSequence text = suggestedWords.getWord(index);
                 word.setText(text);
                 word.setTextScaleX(1.0f);
                 word.setCompoundDrawables(null, null, null, null);
@@ -635,13 +636,13 @@
         mKeyboardView = (KeyboardView)inputView.findViewById(R.id.keyboard_view);
     }
 
-    public void setSuggestions(SuggestedWords suggestions) {
-        if (suggestions == null || suggestions.size() == 0)
+    public void setSuggestions(SuggestedWords suggestedWords) {
+        if (suggestedWords == null || suggestedWords.size() == 0)
             return;
 
         clear();
-        mSuggestions = suggestions;
-        mParams.layout(mSuggestions, mSuggestionsStrip, this, getWidth());
+        mSuggestedWords = suggestedWords;
+        mParams.layout(mSuggestedWords, mSuggestionsStrip, this, getWidth());
     }
 
 
@@ -664,7 +665,7 @@
     }
 
     public SuggestedWords getSuggestions() {
-        return mSuggestions;
+        return mSuggestedWords;
     }
 
     public void clear() {
@@ -687,7 +688,7 @@
         @Override
         public boolean onCustomRequest(int requestCode) {
             final int index = requestCode;
-            final CharSequence word = mSuggestions.getWord(index);
+            final CharSequence word = mSuggestedWords.getWord(index);
             mListener.pickSuggestionManually(index, word);
             dismissMoreSuggestions();
             return true;
@@ -732,7 +733,7 @@
             final int maxWidth = stripWidth - container.getPaddingLeft()
                     - container.getPaddingRight();
             final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder;
-            builder.layout(mSuggestions, params.mSuggestionsCountInStrip, maxWidth,
+            builder.layout(mSuggestedWords, params.mSuggestionsCountInStrip, maxWidth,
                     (int)(maxWidth * params.mMinMoreSuggestionsWidth),
                     params.mMaxMoreSuggestionsRow);
             mMoreSuggestionsView.setKeyboard(builder.build());
@@ -834,10 +835,10 @@
         if (!(tag instanceof Integer))
             return;
         final int index = (Integer) tag;
-        if (index >= mSuggestions.size())
+        if (index >= mSuggestedWords.size())
             return;
 
-        final CharSequence word = mSuggestions.getWord(index);
+        final CharSequence word = mSuggestedWords.getWord(index);
         mListener.pickSuggestionManually(index, word);
     }