1732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang/**
2732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang * Copyright (c) 2012, Google Inc.
3732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang *
4732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang * Licensed under the Apache License, Version 2.0 (the "License");
5732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang * you may not use this file except in compliance with the License.
6732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang * You may obtain a copy of the License at
7732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang *
8732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang *     http://www.apache.org/licenses/LICENSE-2.0
9732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang *
10732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang * Unless required by applicable law or agreed to in writing, software
11732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang * distributed under the License is distributed on an "AS IS" BASIS,
12732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang * See the License for the specific language governing permissions and
14732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang * limitations under the License.
15732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang */
16732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
17732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangpackage com.android.mail.providers;
18732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
191bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huangimport android.content.ContentValues;
20bf9508d3877d05742b2f5d23e1780366d3e1aa2eMindy Pereiraimport android.content.Context;
21732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport android.database.Cursor;
22732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport android.net.Uri;
237f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huangimport android.os.Bundle;
24732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport android.os.Parcel;
25732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport android.os.Parcelable;
26e623a0f6e3caa9cafec913cf826e946628833517Andy Huangimport android.provider.BaseColumns;
275c765b9c5dd8a9a9421260ba8b46d06073391c73Mindy Pereiraimport android.text.TextUtils;
28732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
29bf9508d3877d05742b2f5d23e1780366d3e1aa2eMindy Pereiraimport com.android.mail.R;
305f578144cc01738d5f9988d61674a643df19fdaeScott Kennedyimport com.android.mail.browse.ConversationCursor;
315f578144cc01738d5f9988d61674a643df19fdaeScott Kennedyimport com.android.mail.content.CursorCreator;
32ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereiraimport com.android.mail.providers.UIProvider.ConversationColumns;
331367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrookimport com.android.mail.providers.UIProvider.ConversationCursorCommand;
345f578144cc01738d5f9988d61674a643df19fdaeScott Kennedyimport com.android.mail.ui.ConversationCursorLoader;
359e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huangimport com.android.mail.utils.LogTag;
369e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huangimport com.android.mail.utils.LogUtils;
37a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blankimport com.google.common.collect.ImmutableList;
38a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank
39440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwalimport java.util.Collection;
40440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwalimport java.util.Collections;
41b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huangimport java.util.List;
42440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal
43732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangpublic class Conversation implements Parcelable {
44f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank    public static final int NO_POSITION = -1;
45732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
469e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang    private static final String LOG_TAG = LogTag.getLogTag();
479e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang
48820f051b37b45b3e3729bda5c4302a879ee6aa4dPaul Westbrook    private static final String EMPTY_STRING = "";
49820f051b37b45b3e3729bda5c4302a879ee6aa4dPaul Westbrook
50e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
51e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see BaseColumns#_ID
52e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
53edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final long id;
54e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
55e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#URI
56e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
57edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final Uri uri;
58e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
59e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#SUBJECT
60e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
61edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final String subject;
62e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
63e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#DATE_RECEIVED_MS
64e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
65edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final long dateMs;
66e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
67e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#HAS_ATTACHMENTS
68e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
69edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final boolean hasAttachments;
70e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
71e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#MESSAGE_LIST_URI
72e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
73edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final Uri messageListUri;
74e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
75e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#SENDING_STATE
76e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
77edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final int sendingState;
78e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
79e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#PRIORITY
80e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
814db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int priority;
82e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
83e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#READ
84e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
85c8a994227b9c686d88ee05840544162711a85712Marc Blank    public boolean read;
86e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
87d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy     * @see UIProvider.ConversationColumns#SEEN
88d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy     */
89d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy    public boolean seen;
90d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy    /**
91e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#STARRED
92e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
93c8a994227b9c686d88ee05840544162711a85712Marc Blank    public boolean starred;
94e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
95e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#RAW_FOLDERS
96e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
97b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang    private FolderList rawFolders;
98e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
99e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#FLAGS
100e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
10122657529437c160dec072115c5982409306c1313Mindy Pereira    public int convFlags;
102e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
103e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#PERSONAL_LEVEL
104e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
105edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final int personalLevel;
106e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
107e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#SPAM
108e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
109edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final boolean spam;
110e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
111e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#MUTED
112e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
113edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final boolean muted;
114e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
11576b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook     * @see UIProvider.ConversationColumns#PHISHING
11676b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook     */
117edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final boolean phishing;
11876b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook    /**
119e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#COLOR
120e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
121edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final int color;
122e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
123e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#ACCOUNT_URI
124e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
125edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final Uri accountUri;
126648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    /**
127648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * @see UIProvider.ConversationColumns#CONVERSATION_INFO
128648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     */
129edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final ConversationInfo conversationInfo;
13041dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook    /**
131cebcc64fbd69618ff89f9fac0bfe9b9e7d7ce104Paul Westbrook     * @see UIProvider.ConversationColumns#CONVERSATION_BASE_URI
13241dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook     */
133edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final Uri conversationBaseUri;
134f98bc898cbc7014a203c35a13427d3f949bce705Andy Huang    /**
135f98bc898cbc7014a203c35a13427d3f949bce705Andy Huang     * @see UIProvider.ConversationColumns#REMOTE
136f98bc898cbc7014a203c35a13427d3f949bce705Andy Huang     */
137edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public final boolean isRemote;
138c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau    /**
139c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau     * @see UIProvider.ConversationColumns#ORDER_KEY
140c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau     */
141c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau    public final long orderKey;
14222657529437c160dec072115c5982409306c1313Mindy Pereira
143dbb587f15c723ae80edb33f65c29cc2b6c15eba0Scott Kennedy    /**
144dbb587f15c723ae80edb33f65c29cc2b6c15eba0Scott Kennedy     * Used within the UI to indicate the adapter position of this conversation
145dbb587f15c723ae80edb33f65c29cc2b6c15eba0Scott Kennedy     *
146dbb587f15c723ae80edb33f65c29cc2b6c15eba0Scott Kennedy     * @deprecated Keeping this in sync with the desired value is a not always done properly, is a
147dbb587f15c723ae80edb33f65c29cc2b6c15eba0Scott Kennedy     *             source of bugs, and is a bad idea in general. Do not trust this value. Try to
148dbb587f15c723ae80edb33f65c29cc2b6c15eba0Scott Kennedy     *             migrate code away from using it.
149dbb587f15c723ae80edb33f65c29cc2b6c15eba0Scott Kennedy     */
150dbb587f15c723ae80edb33f65c29cc2b6c15eba0Scott Kennedy    @Deprecated
151f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank    public transient int position;
152648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // Used within the UI to indicate that a Conversation should be removed from
153648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // the ConversationCursor when executing an update, e.g. the the
154648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // Conversation is no longer in the ConversationList for the current folder,
155648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // that is it's now in some other folder(s)
156ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    public transient boolean localDeleteOnUpdate;
157732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
158cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang    private transient boolean viewed;
159cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang
160928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux    private static String sBadgeAndSubject;
1612909b7442130800d6c6c20c1227d65295262f03emindyp
162e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    // Constituents of convFlags below
163648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // Flag indicating that the item has been deleted, but will continue being
164648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // shown in the list Delete/Archive of a mostly-dead item will NOT propagate
165648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // the delete/archive, but WILL remove the item from the cursor
166e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    public static final int FLAG_MOSTLY_DEAD = 1 << 0;
167e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank
168440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    /** An immutable, empty conversation list */
169440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    public static final Collection<Conversation> EMPTY = Collections.emptyList();
170440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal
171732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
172732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public int describeContents() {
173732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        return 0;
174732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
175732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
176732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
177732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public void writeToParcel(Parcel dest, int flags) {
178732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeLong(id);
179c43bc0a606e41144a780c4f873b5450e0ede0c91Marc Blank        dest.writeParcelable(uri, flags);
180732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeString(subject);
181732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeLong(dateMs);
182f98bc898cbc7014a203c35a13427d3f949bce705Andy Huang        dest.writeInt(hasAttachments ? 1 : 0);
183cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira        dest.writeParcelable(messageListUri, 0);
1844db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(sendingState);
1854db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(priority);
186f98bc898cbc7014a203c35a13427d3f949bce705Andy Huang        dest.writeInt(read ? 1 : 0);
187d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy        dest.writeInt(seen ? 1 : 0);
188f98bc898cbc7014a203c35a13427d3f949bce705Andy Huang        dest.writeInt(starred ? 1 : 0);
189b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang        dest.writeParcelable(rawFolders, 0);
19022657529437c160dec072115c5982409306c1313Mindy Pereira        dest.writeInt(convFlags);
19122657529437c160dec072115c5982409306c1313Mindy Pereira        dest.writeInt(personalLevel);
192863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        dest.writeInt(spam ? 1 : 0);
19376b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook        dest.writeInt(phishing ? 1 : 0);
194863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        dest.writeInt(muted ? 1 : 0);
19592939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank        dest.writeInt(color);
196a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank        dest.writeParcelable(accountUri, 0);
197351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huang        dest.writeParcelable(conversationInfo, 0);
19841dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook        dest.writeParcelable(conversationBaseUri, 0);
199f98bc898cbc7014a203c35a13427d3f949bce705Andy Huang        dest.writeInt(isRemote ? 1 : 0);
200c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau        dest.writeLong(orderKey);
201732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
202732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
203351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huang    private Conversation(Parcel in, ClassLoader loader) {
204732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        id = in.readLong();
205c43bc0a606e41144a780c4f873b5450e0ede0c91Marc Blank        uri = in.readParcelable(null);
206732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        subject = in.readString();
207732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dateMs = in.readLong();
208f98bc898cbc7014a203c35a13427d3f949bce705Andy Huang        hasAttachments = (in.readInt() != 0);
209cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira        messageListUri = in.readParcelable(null);
2104db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        sendingState = in.readInt();
2114db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        priority = in.readInt();
212f98bc898cbc7014a203c35a13427d3f949bce705Andy Huang        read = (in.readInt() != 0);
213d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy        seen = (in.readInt() != 0);
214f98bc898cbc7014a203c35a13427d3f949bce705Andy Huang        starred = (in.readInt() != 0);
215b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang        rawFolders = in.readParcelable(loader);
21622657529437c160dec072115c5982409306c1313Mindy Pereira        convFlags = in.readInt();
21722657529437c160dec072115c5982409306c1313Mindy Pereira        personalLevel = in.readInt();
218863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        spam = in.readInt() != 0;
21976b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook        phishing = in.readInt() != 0;
220863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        muted = in.readInt() != 0;
22192939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank        color = in.readInt();
222a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank        accountUri = in.readParcelable(null);
223f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank        position = NO_POSITION;
224ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        localDeleteOnUpdate = false;
225351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huang        conversationInfo = in.readParcelable(loader);
22641dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook        conversationBaseUri = in.readParcelable(null);
227f98bc898cbc7014a203c35a13427d3f949bce705Andy Huang        isRemote = in.readInt() != 0;
228c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau        orderKey = in.readLong();
229732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
230732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
231732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
232732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public String toString() {
2339e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang        // log extra info at DEBUG level or finer
2349e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang        final StringBuilder sb = new StringBuilder("[conversation id=");
2359e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang        sb.append(id);
2369e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang        if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)) {
2379e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang            sb.append(", subject=");
2389e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang            sb.append(subject);
2399e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang        }
2409e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang        sb.append("]");
2419e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang        return sb.toString();
242732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
243732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
244351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huang    public static final ClassLoaderCreator<Conversation> CREATOR =
245351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huang            new ClassLoaderCreator<Conversation>() {
246732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
247732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        @Override
248732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        public Conversation createFromParcel(Parcel source) {
249351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huang            return new Conversation(source, null);
250351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huang        }
251351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huang
252351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huang        @Override
253351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huang        public Conversation createFromParcel(Parcel source, ClassLoader loader) {
254351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huang            return new Conversation(source, loader);
255732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
256732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
257732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        @Override
258732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        public Conversation[] newArray(int size) {
259732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            return new Conversation[size];
260732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
261732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
262732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    };
263732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
264acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira    public static final Uri MOVE_CONVERSATIONS_URI = Uri.parse("content://moveconversations");
265acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira
266ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira    /**
267ae7e6a0786a2d890b77c783d7ac39a90523b8154mindyp     * The column that needs to be updated to change the folders for a conversation.
268ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira     */
26900ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira    public static final String UPDATE_FOLDER_COLUMN = ConversationColumns.RAW_FOLDERS;
270ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira
271a831b2f1ba6d3c18d5e54563df8bae1f589c4257Mindy Pereira    public Conversation(Cursor cursor) {
272edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        if (cursor == null) {
273edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            throw new IllegalArgumentException("Creating conversation from null cursor");
274edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
275edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        id = cursor.getLong(UIProvider.CONVERSATION_ID_COLUMN);
276edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        uri = Uri.parse(cursor.getString(UIProvider.CONVERSATION_URI_COLUMN));
277edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        dateMs = cursor.getLong(UIProvider.CONVERSATION_DATE_RECEIVED_MS_COLUMN);
278edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        final String subj = cursor.getString(UIProvider.CONVERSATION_SUBJECT_COLUMN);
279edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        // Don't allow null subject
280edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        if (subj == null) {
281edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            subject = "";
282edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        } else {
283edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            subject = subj;
284732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
285edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        hasAttachments = cursor.getInt(UIProvider.CONVERSATION_HAS_ATTACHMENTS_COLUMN) != 0;
286edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        String messageList = cursor.getString(UIProvider.CONVERSATION_MESSAGE_LIST_URI_COLUMN);
287edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        messageListUri = !TextUtils.isEmpty(messageList) ? Uri.parse(messageList) : null;
288edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        sendingState = cursor.getInt(UIProvider.CONVERSATION_SENDING_STATE_COLUMN);
289edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        priority = cursor.getInt(UIProvider.CONVERSATION_PRIORITY_COLUMN);
290edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        read = cursor.getInt(UIProvider.CONVERSATION_READ_COLUMN) != 0;
291edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        seen = cursor.getInt(UIProvider.CONVERSATION_SEEN_COLUMN) != 0;
292edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        starred = cursor.getInt(UIProvider.CONVERSATION_STARRED_COLUMN) != 0;
293edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        rawFolders = readRawFolders(cursor);
294edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        convFlags = cursor.getInt(UIProvider.CONVERSATION_FLAGS_COLUMN);
295edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        personalLevel = cursor.getInt(UIProvider.CONVERSATION_PERSONAL_LEVEL_COLUMN);
296edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        spam = cursor.getInt(UIProvider.CONVERSATION_IS_SPAM_COLUMN) != 0;
297edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        phishing = cursor.getInt(UIProvider.CONVERSATION_IS_PHISHING_COLUMN) != 0;
298edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        muted = cursor.getInt(UIProvider.CONVERSATION_MUTED_COLUMN) != 0;
299edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        color = cursor.getInt(UIProvider.CONVERSATION_COLOR_COLUMN);
300edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        String account = cursor.getString(UIProvider.CONVERSATION_ACCOUNT_URI_COLUMN);
301edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        accountUri = !TextUtils.isEmpty(account) ? Uri.parse(account) : null;
302edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        position = NO_POSITION;
303edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        localDeleteOnUpdate = false;
304edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        conversationInfo = readConversationInfo(cursor);
305edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        if (conversationInfo == null) {
306edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            LogUtils.wtf(LOG_TAG, "Null conversation info from cursor");
307edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
308edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        final String conversationBase =
309edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler                cursor.getString(UIProvider.CONVERSATION_BASE_URI_COLUMN);
310edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        conversationBaseUri = !TextUtils.isEmpty(conversationBase) ?
311edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler                Uri.parse(conversationBase) : null;
312edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        isRemote = cursor.getInt(UIProvider.CONVERSATION_REMOTE_COLUMN) != 0;
313c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau        orderKey = cursor.getLong(UIProvider.CONVERSATION_ORDER_KEY_COLUMN);
314732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
315732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
3161bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang    public Conversation(Conversation other) {
3171bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        if (other == null) {
318edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            throw new IllegalArgumentException("Copying null conversation");
3191bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        }
3201bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang
3211bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        id = other.id;
3221bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        uri = other.uri;
3231bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        dateMs = other.dateMs;
3241bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        subject = other.subject;
3251bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        hasAttachments = other.hasAttachments;
3261bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        messageListUri = other.messageListUri;
3271bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        sendingState = other.sendingState;
3281bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        priority = other.priority;
3291bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        read = other.read;
3301bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        seen = other.seen;
3311bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        starred = other.starred;
3321bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        rawFolders = other.rawFolders; // FolderList is immutable, shallow copy is OK
3331bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        convFlags = other.convFlags;
3341bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        personalLevel = other.personalLevel;
3351bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        spam = other.spam;
3361bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        phishing = other.phishing;
3371bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        muted = other.muted;
3381bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        color = other.color;
3391bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        accountUri = other.accountUri;
3401bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        position = other.position;
3411bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        localDeleteOnUpdate = other.localDeleteOnUpdate;
3421bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        // although ConversationInfo is mutable (see ConversationInfo.markRead), applyCachedValues
3431bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        // will overwrite this if cached changes exist anyway, so a shallow copy is OK
3441bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        conversationInfo = other.conversationInfo;
3451bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        conversationBaseUri = other.conversationBaseUri;
3461bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        isRemote = other.isRemote;
347c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau        orderKey = other.orderKey;
3481bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang    }
3491bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang
350f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein    private Conversation(long id, Uri uri, String subject, long dateMs,
351edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            boolean hasAttachment, Uri messageListUri,
352edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            int sendingState, int priority, boolean read,
353d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy            boolean seen, boolean starred, FolderList rawFolders, int convFlags, int personalLevel,
354d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy            boolean spam, boolean phishing, boolean muted, Uri accountUri,
355479505d71969e26b0785d8e0e1b81108731cf827Mark Wei            ConversationInfo conversationInfo, Uri conversationBase, boolean isRemote,
3560e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux            String permalink, long orderKey) {
357edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        if (conversationInfo == null) {
358edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            throw new IllegalArgumentException("Null conversationInfo");
359edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
360edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.id = id;
361edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.uri = uri;
362edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.subject = subject;
363edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.dateMs = dateMs;
364edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.hasAttachments = hasAttachment;
365edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.messageListUri = messageListUri;
366edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.sendingState = sendingState;
367edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.priority = priority;
368edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.read = read;
369edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.seen = seen;
370edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.starred = starred;
371edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.rawFolders = rawFolders;
372edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.convFlags = convFlags;
373edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.personalLevel = personalLevel;
374edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.spam = spam;
375edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.phishing = phishing;
376edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.muted = muted;
377edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.color = 0;
378edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.accountUri = accountUri;
379edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.conversationInfo = conversationInfo;
380edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.conversationBaseUri = conversationBase;
381edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        this.isRemote = isRemote;
382c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau        this.orderKey = orderKey;
383edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    }
384edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
385edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler    public static class Builder {
386edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private long mId;
387edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private Uri mUri;
388edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private String mSubject;
389edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private long mDateMs;
390edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private boolean mHasAttachments;
391edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private Uri mMessageListUri;
392edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private int mSendingState;
393edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private int mPriority;
394edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private boolean mRead;
395edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private boolean mSeen;
396edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private boolean mStarred;
397edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private FolderList mRawFolders;
398edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private int mConvFlags;
399edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private int mPersonalLevel;
400edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private boolean mSpam;
401edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private boolean mPhishing;
402edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private boolean mMuted;
403edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private Uri mAccountUri;
404edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private ConversationInfo mConversationInfo;
405edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private Uri mConversationBaseUri;
406edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        private boolean mIsRemote;
407f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein        private String mPermalink;
408c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau        private long mOrderKey;
409edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
410edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setId(long id) {
411edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mId = id;
412edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
413edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
414edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
415edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setUri(Uri uri) {
416edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mUri = uri;
417edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
418edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
419edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
420edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setSubject(String subject) {
421edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mSubject = subject;
422edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
423edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
424edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
425edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setDateMs(long dateMs) {
426edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mDateMs = dateMs;
427edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
428edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
429edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
430edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setHasAttachments(boolean hasAttachments) {
431edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mHasAttachments = hasAttachments;
432edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
433edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
434edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
435edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setMessageListUri(Uri messageListUri) {
436edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mMessageListUri = messageListUri;
437edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
438edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
439edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
440edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setSendingState(int sendingState) {
441edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mSendingState = sendingState;
442edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
443edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
444edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
445edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setPriority(int priority) {
446edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mPriority = priority;
447edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
448edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
449edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
450edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setRead(boolean read) {
451edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mRead = read;
452edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
453edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
454edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
455edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setSeen(boolean seen) {
456edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mSeen = seen;
457edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
458edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
459edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
460edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setStarred(boolean starred) {
461edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mStarred = starred;
462edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
463edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
464edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
465edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setRawFolders(FolderList rawFolders) {
466edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mRawFolders = rawFolders;
467edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
468edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
469edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
470edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setConvFlags(int convFlags) {
471edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mConvFlags = convFlags;
472edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
473edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
474edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
475edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setPersonalLevel(int personalLevel) {
476edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mPersonalLevel = personalLevel;
477edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
478edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
479edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
480edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setSpam(boolean spam) {
481edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mSpam = spam;
482edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
483edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
484edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
485edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setPhishing(boolean phishing) {
486edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mPhishing = phishing;
487edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
488edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
489edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
490edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setMuted(boolean muted) {
491edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mMuted = muted;
492edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
493edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
494edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
495edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setAccountUri(Uri accountUri) {
496edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mAccountUri = accountUri;
497edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
498edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
499edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
500edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setConversationInfo(ConversationInfo conversationInfo) {
501edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            if (conversationInfo == null) {
502edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler                throw new IllegalArgumentException("Can't set null ConversationInfo");
503edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            }
504edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mConversationInfo = conversationInfo;
505edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
506edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
507edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
508edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setConversationBaseUri(Uri conversationBaseUri) {
509edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mConversationBaseUri = conversationBaseUri;
510edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
511edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
512edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
513edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder setIsRemote(boolean isRemote) {
514edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            mIsRemote = isRemote;
515edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return this;
516edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
517edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
518f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein        public Builder setPermalink(String permalink) {
519f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein            mPermalink = permalink;
520f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein            return this;
521f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein        }
522f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein
523c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau        public Builder setOrderKey(long orderKey) {
524c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau            mOrderKey = orderKey;
525c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau            return this;
526c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau        }
527c92dc65f64e8b09ee78ba2fa799d7d3627373913Alan Lau
528edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Builder() {}
529edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler
530edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        public Conversation build() {
531edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            if (mConversationInfo == null) {
532edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler                LogUtils.d(LOG_TAG, "Null conversationInfo in Builder");
533edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler                mConversationInfo = new ConversationInfo();
534edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            }
535edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler            return new Conversation(mId, mUri, mSubject, mDateMs, mHasAttachments, mMessageListUri,
536edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler                    mSendingState, mPriority, mRead, mSeen, mStarred, mRawFolders, mConvFlags,
537edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler                    mPersonalLevel, mSpam, mPhishing, mMuted, mAccountUri, mConversationInfo,
5380e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux                    mConversationBaseUri, mIsRemote, mPermalink, mOrderKey);
539edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        }
540ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook    }
541ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook
5421367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook    private static final Bundle CONVERSATION_INFO_REQUEST;
5431367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook    private static final Bundle RAW_FOLDERS_REQUEST;
5441367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook
5451367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook    static {
5461367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook        RAW_FOLDERS_REQUEST = new Bundle(2);
5471367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook        RAW_FOLDERS_REQUEST.putBoolean(
5481367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook                ConversationCursorCommand.COMMAND_GET_RAW_FOLDERS, true);
5491367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook        RAW_FOLDERS_REQUEST.putInt(
5501367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook                ConversationCursorCommand.COMMAND_KEY_OPTIONS,
5511367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook                ConversationCursorCommand.OPTION_MOVE_POSITION);
5521367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook
5531367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook        CONVERSATION_INFO_REQUEST = new Bundle(2);
5541367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook        CONVERSATION_INFO_REQUEST.putBoolean(
5551367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook                ConversationCursorCommand.COMMAND_GET_CONVERSATION_INFO, true);
5561367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook        CONVERSATION_INFO_REQUEST.putInt(
5571367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook                ConversationCursorCommand.COMMAND_KEY_OPTIONS,
5581367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook                ConversationCursorCommand.OPTION_MOVE_POSITION);
5591367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook    }
5607f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang
5617f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang    private static ConversationInfo readConversationInfo(Cursor cursor) {
5627f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang        final ConversationInfo ci;
5637f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang
564f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang        if (cursor instanceof ConversationCursor) {
565f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang            final byte[] blob = ((ConversationCursor) cursor).getCachedBlob(
566f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang                    UIProvider.CONVERSATION_INFO_COLUMN);
567f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang            if (blob != null && blob.length > 0) {
568f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang                return ConversationInfo.fromBlob(blob);
569f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang            }
570f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang        }
571f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang
5721367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook        final Bundle response = cursor.respond(CONVERSATION_INFO_REQUEST);
5731367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook        if (response.containsKey(ConversationCursorCommand.COMMAND_GET_CONVERSATION_INFO)) {
5741367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook            ci = response.getParcelable(ConversationCursorCommand.COMMAND_GET_CONVERSATION_INFO);
5757f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang        } else {
5767f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang            // legacy fallback
5777f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang            ci = ConversationInfo.fromBlob(cursor.getBlob(UIProvider.CONVERSATION_INFO_COLUMN));
5787f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang        }
5797f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang        return ci;
5807f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang    }
5817f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang
5827f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang    private static FolderList readRawFolders(Cursor cursor) {
5837f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang        final FolderList fl;
5847f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang
585f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang        if (cursor instanceof ConversationCursor) {
586f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang            final byte[] blob = ((ConversationCursor) cursor).getCachedBlob(
587f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang                    UIProvider.CONVERSATION_RAW_FOLDERS_COLUMN);
588f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang            if (blob != null && blob.length > 0) {
589f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang                return FolderList.fromBlob(blob);
590f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang            }
591f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang        }
592f8b613c1103952ae5cc1f8a5e6ae60aa62d73decAndy Huang
5931367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook        final Bundle response = cursor.respond(RAW_FOLDERS_REQUEST);
5941367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook        if (response.containsKey(ConversationCursorCommand.COMMAND_GET_RAW_FOLDERS)) {
5951367d09b1cb2ea08f2e105672262ade08e1f5895Paul Westbrook            fl = response.getParcelable(ConversationCursorCommand.COMMAND_GET_RAW_FOLDERS);
5967f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang        } else {
5977f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang            // legacy fallback
598db5356a92ebc593e9eb564aaadad8dac8cd83554Paul Westbrook            // TODO: delete this once Email supports the respond call
5997f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang            fl = FolderList.fromBlob(
6007f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang                    cursor.getBlob(UIProvider.CONVERSATION_RAW_FOLDERS_COLUMN));
6017f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang        }
6027f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang        return fl;
6037f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang    }
6047f39bbd358f7003a72ae2b480dfe38a84e830e5fAndy Huang
605b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang    /**
6061bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang     * Apply any column values from the given {@link ContentValues} (where column names are the
6071bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang     * keys) to this conversation.
6081bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang     *
6091bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang     */
6101bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang    public void applyCachedValues(ContentValues values) {
6111bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        if (values == null) {
6121bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang            return;
6131bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        }
6141bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        for (String key : values.keySet()) {
6151bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang            final Object val = values.get(key);
6161bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang            LogUtils.i(LOG_TAG, "Conversation: applying cached value to col=%s val=%s", key,
6171bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang                    val);
6181bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang            if (ConversationColumns.READ.equals(key)) {
6191bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang                read = (Integer) val != 0;
6201bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang            } else if (ConversationColumns.CONVERSATION_INFO.equals(key)) {
621edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler                final ConversationInfo cachedCi = ConversationInfo.fromBlob((byte[]) val);
622edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler                if (cachedCi == null) {
623edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler                    LogUtils.d(LOG_TAG, "Null ConversationInfo in applyCachedValues");
624edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler                } else {
625edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler                    conversationInfo.overwriteWith(cachedCi);
626edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler                }
6271bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang            } else if (ConversationColumns.FLAGS.equals(key)) {
6281bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang                convFlags = (Integer) val;
6291bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang            } else if (ConversationColumns.STARRED.equals(key)) {
6301bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang                starred = (Integer) val != 0;
6317f4b6140b40c1d1d2624ca1dabe229fbb5c6959aAndy Huang            } else if (ConversationColumns.SEEN.equals(key)) {
6327f4b6140b40c1d1d2624ca1dabe229fbb5c6959aAndy Huang                seen = (Integer) val != 0;
6338ebc2ce34ed7d979662cf88b1c9fa60d63142fe4Andy Huang            } else if (ConversationColumns.RAW_FOLDERS.equals(key)) {
6348ebc2ce34ed7d979662cf88b1c9fa60d63142fe4Andy Huang                rawFolders = FolderList.fromBlob((byte[]) val);
6351bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang            } else if (ConversationColumns.VIEWED.equals(key)) {
6361bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang                // ignore. this is not read from the cursor, either.
6378ce148c14ca2a3491ee64847f287f3f46079df2dJin Cao            } else if (ConversationColumns.PRIORITY.equals(key)) {
6388ce148c14ca2a3491ee64847f287f3f46079df2dJin Cao                priority = (Integer) val;
6391bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang            } else {
6401bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang                LogUtils.e(LOG_TAG, new UnsupportedOperationException(),
6411bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang                        "unsupported cached conv value in col=%s", key);
6421bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang            }
6431bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang        }
6441bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang    }
6451bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang
6461bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang    /**
647b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang     * Get the <strong>immutable</strong> list of {@link Folder}s for this conversation. To modify
648b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang     * this list, make a new {@link FolderList} and use {@link #setRawFolders(FolderList)}.
649b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang     *
650b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang     * @return <strong>Immutable</strong> list of {@link Folder}s.
651b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang     */
652b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang    public List<Folder> getRawFolders() {
653b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang        return rawFolders.folders;
65400ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira    }
65500ffece08e94ff5774b2a53c0adeb2f3d0815d66Mindy Pereira
656b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang    public void setRawFolders(FolderList folders) {
657b2033d855ab0f13e253e5403ce25989bcbc49488Andy Huang        rawFolders = folders;
65885c4a77abd849f5f3f0236d51554bb1bb99fe8f6Mindy Pereira    }
65985c4a77abd849f5f3f0236d51554bb1bb99fe8f6Mindy Pereira
660e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    @Override
661e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    public boolean equals(Object o) {
6623c9bcef43b4f103697034abbf2eab99111e8d987Marc Blank        if (o instanceof Conversation) {
663648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            Conversation conv = (Conversation) o;
6643c9bcef43b4f103697034abbf2eab99111e8d987Marc Blank            return conv.uri.equals(uri);
6653c9bcef43b4f103697034abbf2eab99111e8d987Marc Blank        }
6663c9bcef43b4f103697034abbf2eab99111e8d987Marc Blank        return false;
667e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    }
668e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank
669e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    @Override
670e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    public int hashCode() {
671e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank        return uri.hashCode();
672e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    }
673e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank
6747f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    /**
6757f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira     * Get if this conversation is marked as high priority.
6767f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira     */
6777f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    public boolean isImportant() {
67822657529437c160dec072115c5982409306c1313Mindy Pereira        return priority == UIProvider.ConversationPriority.IMPORTANT;
6797f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    }
6807f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira
681e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    /**
682e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank     * Get if this conversation is mostly dead
683e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank     */
684e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    public boolean isMostlyDead() {
685e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank        return (convFlags & FLAG_MOSTLY_DEAD) != 0;
686e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    }
687440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal
688440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    /**
689648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * Returns true if the URI of the conversation specified as the needle was
690648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * found in the collection of conversations specified as the haystack. False
691192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal     * otherwise. This method is safe to call with null arguments.
692f98bc898cbc7014a203c35a13427d3f949bce705Andy Huang     *
693d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal     * @param haystack
694d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal     * @param needle
695d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal     * @return true if the needle was found in the haystack, false otherwise.
696d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal     */
697d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal    public final static boolean contains(Collection<Conversation> haystack, Conversation needle) {
698d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        // If the haystack is empty, it cannot contain anything.
699d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        if (haystack == null || haystack.size() <= 0) {
700d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal            return false;
701d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        }
702d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        // The null folder exists everywhere.
703d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        if (needle == null) {
704d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal            return true;
705d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        }
7067dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        final long toFind = needle.id;
707d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        for (final Conversation c : haystack) {
7087dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal            if (toFind == c.id) {
709d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal                return true;
710d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal            }
711d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        }
712d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        return false;
713d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal    }
714d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal
715d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal    /**
716648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * Returns a collection of a single conversation. This method always returns
717648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * a valid collection even if the input conversation is null.
718f98bc898cbc7014a203c35a13427d3f949bce705Andy Huang     *
719440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal     * @param in a conversation, possibly null.
720440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal     * @return a collection of the conversation.
721440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal     */
722440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    public static Collection<Conversation> listOf(Conversation in) {
723440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal        final Collection<Conversation> target = (in == null) ? EMPTY : ImmutableList.of(in);
724440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal        return target;
725440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    }
7267dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal
7277dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal    /**
728edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler     * Get the snippet for this conversation.
729aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira     */
730aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira    public String getSnippet() {
731edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        return !TextUtils.isEmpty(conversationInfo.firstSnippet) ?
732edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler                conversationInfo.firstSnippet : "";
733aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira    }
734aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira
735aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira    /**
7360972e0793cc321670391d063348aecb5031b2677Mindy Pereira     * Get the number of messages for this conversation.
7370972e0793cc321670391d063348aecb5031b2677Mindy Pereira     */
7380972e0793cc321670391d063348aecb5031b2677Mindy Pereira    public int getNumMessages() {
739edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        return conversationInfo.messageCount;
7400972e0793cc321670391d063348aecb5031b2677Mindy Pereira    }
7410972e0793cc321670391d063348aecb5031b2677Mindy Pereira
7420972e0793cc321670391d063348aecb5031b2677Mindy Pereira    /**
7430972e0793cc321670391d063348aecb5031b2677Mindy Pereira     * Get the number of drafts for this conversation.
7440972e0793cc321670391d063348aecb5031b2677Mindy Pereira     */
7450972e0793cc321670391d063348aecb5031b2677Mindy Pereira    public int numDrafts() {
746edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler        return conversationInfo.draftCount;
7470972e0793cc321670391d063348aecb5031b2677Mindy Pereira    }
7480972e0793cc321670391d063348aecb5031b2677Mindy Pereira
749cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang    public boolean isViewed() {
750cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang        return viewed;
751cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang    }
752cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang
753cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang    public void markViewed() {
754cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang        viewed = true;
755cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang    }
756cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang
757c1fb9a9c2730178105977fca629e80951bfc3cdcAndy Huang    public String getBaseUri(String defaultValue) {
758c1fb9a9c2730178105977fca629e80951bfc3cdcAndy Huang        return conversationBaseUri != null ? conversationBaseUri.toString() : defaultValue;
759c1fb9a9c2730178105977fca629e80951bfc3cdcAndy Huang    }
760c1fb9a9c2730178105977fca629e80951bfc3cdcAndy Huang
7610972e0793cc321670391d063348aecb5031b2677Mindy Pereira    /**
7627dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     * Create a human-readable string of all the conversations
7637dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     * @param collection Any collection of conversations
7647dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     * @return string with a human readable representation of the conversations.
7657dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     */
7667dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal    public static String toString(Collection<Conversation> collection) {
7677dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        final StringBuilder out = new StringBuilder(collection.size() + " conversations:");
7687dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        int count = 0;
7697dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        for (final Conversation c : collection) {
7707dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal            count++;
771648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            // Indent the conversations to make them easy to read in debug
772648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            // output.
7737dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal            out.append("      " + count + ": " + c.toString() + "\n");
7747dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        }
7757dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        return out.toString();
7767dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal    }
777820f051b37b45b3e3729bda5c4302a879ee6aa4dPaul Westbrook
778820f051b37b45b3e3729bda5c4302a879ee6aa4dPaul Westbrook    /**
779820f051b37b45b3e3729bda5c4302a879ee6aa4dPaul Westbrook     * Returns an empty string if the specified string is null
780820f051b37b45b3e3729bda5c4302a879ee6aa4dPaul Westbrook     */
781820f051b37b45b3e3729bda5c4302a879ee6aa4dPaul Westbrook    private static String emptyIfNull(String in) {
782820f051b37b45b3e3729bda5c4302a879ee6aa4dPaul Westbrook        return in != null ? in : EMPTY_STRING;
783820f051b37b45b3e3729bda5c4302a879ee6aa4dPaul Westbrook    }
784bf9508d3877d05742b2f5d23e1780366d3e1aa2eMindy Pereira
785bf9508d3877d05742b2f5d23e1780366d3e1aa2eMindy Pereira    /**
786928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux     * Get the properly formatted badge and subject string for displaying a conversation.
787bf9508d3877d05742b2f5d23e1780366d3e1aa2eMindy Pereira     */
788928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux    public static String getSubjectForDisplay(Context context, String badgeText,
789928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux            String filteredSubject) {
790928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux        if (TextUtils.isEmpty(filteredSubject)) {
79194033deeb31df739a27fce15887a3f0a2e808b12James Lemieux            return context.getString(R.string.no_subject);
792be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein        } else if (!TextUtils.isEmpty(badgeText)) {
793928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux            if (sBadgeAndSubject == null) {
794928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux                sBadgeAndSubject = context.getString(R.string.badge_and_subject);
795be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein            }
796928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux            return String.format(sBadgeAndSubject, badgeText, filteredSubject);
79761bd0e84a3b0545a722bbfe931233b47afdf52e2Scott Kennedy        }
79861bd0e84a3b0545a722bbfe931233b47afdf52e2Scott Kennedy
799928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux        return filteredSubject;
800bf9508d3877d05742b2f5d23e1780366d3e1aa2eMindy Pereira    }
8015f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy
8025f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy    /**
8035f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy     * Public object that knows how to construct Conversation given Cursors. This is not used by
8045f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy     * {@link ConversationCursor} or {@link ConversationCursorLoader}.
8055f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy     */
8065f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy    public static final CursorCreator<Conversation> FACTORY = new CursorCreator<Conversation>() {
8075f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy        @Override
8085f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy        public Conversation createFromCursor(final Cursor c) {
8095f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy            return new Conversation(c);
8105f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy        }
8115f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy
8125f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy        @Override
8135f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy        public String toString() {
8145f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy            return "Conversation CursorCreator";
8155f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy        }
8165f578144cc01738d5f9988d61674a643df19fdaeScott Kennedy    };
817648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira}
818