Conversation.java revision 00c67ae6212de5b56c0c94af185061ee2fa36925
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
19732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport android.database.Cursor;
20732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport android.net.Uri;
21732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport android.os.Parcel;
22732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport android.os.Parcelable;
23e623a0f6e3caa9cafec913cf826e946628833517Andy Huangimport android.provider.BaseColumns;
245c765b9c5dd8a9a9421260ba8b46d06073391c73Mindy Pereiraimport android.text.TextUtils;
25732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
26ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereiraimport com.android.mail.providers.UIProvider.ConversationColumns;
27648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereiraimport com.android.mail.utils.LogTag;
28648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereiraimport com.android.mail.utils.LogUtils;
29a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blankimport com.google.common.collect.ImmutableList;
30a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank
31648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereiraimport org.json.JSONException;
32648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira
33440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwalimport java.util.Collection;
34440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwalimport java.util.Collections;
35440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal
36732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangpublic class Conversation implements Parcelable {
37f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank    public static final int NO_POSITION = -1;
38732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
39e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
40e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see BaseColumns#_ID
41e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
42732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public long id;
43e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
44e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#URI
45e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
46c43bc0a606e41144a780c4f873b5450e0ede0c91Marc Blank    public Uri uri;
47e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
48e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#SUBJECT
49e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
50732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public String subject;
51e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
52e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#DATE_RECEIVED_MS
53e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
54732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public long dateMs;
55e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
56e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#SNIPPET
57e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
58aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira    @Deprecated
59732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public String snippet;
60e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
61e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#HAS_ATTACHMENTS
62e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
63732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public boolean hasAttachments;
64e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
65e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#MESSAGE_LIST_URI
66e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
67cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira    public Uri messageListUri;
68e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
69e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#SENDER_INFO
70e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
71648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    @Deprecated
724db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public String senders;
73e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
74e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#NUM_MESSAGES
75e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
764db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int numMessages;
77e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
78e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#NUM_DRAFTS
79e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
804db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int numDrafts;
81e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
82e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#SENDING_STATE
83e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
844db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int sendingState;
85e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
86e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#PRIORITY
87e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
884db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int priority;
89e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
90e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#READ
91e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
92c8a994227b9c686d88ee05840544162711a85712Marc Blank    public boolean read;
93e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
94e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#STARRED
95e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
96c8a994227b9c686d88ee05840544162711a85712Marc Blank    public boolean starred;
97e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
98e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#FOLDER_LIST
99e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
100ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    public String folderList;
101e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
102e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#RAW_FOLDERS
103e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
104cc8211df898ba9dac17a766b89f28d6e6f0afef0Mindy Pereira    public String rawFolders;
105e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
106e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#FLAGS
107e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
10822657529437c160dec072115c5982409306c1313Mindy Pereira    public int convFlags;
109e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
110e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#PERSONAL_LEVEL
111e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
11222657529437c160dec072115c5982409306c1313Mindy Pereira    public int personalLevel;
113e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
114e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#SPAM
115e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
116863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira    public boolean spam;
117e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
118e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#MUTED
119e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
120863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira    public boolean muted;
121e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
12276b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook     * @see UIProvider.ConversationColumns#PHISHING
12376b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook     */
12476b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook    public boolean phishing;
12576b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook    /**
126e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#COLOR
127e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
12892939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank    public int color;
129e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
130e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#ACCOUNT_URI
131e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
132a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank    public Uri accountUri;
133648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    /**
134648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * @see UIProvider.ConversationColumns#CONVERSATION_INFO
135648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     */
136648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    public ConversationInfo conversationInfo;
13722657529437c160dec072115c5982409306c1313Mindy Pereira
138ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    // Used within the UI to indicate the adapter position of this conversation
139f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank    public transient int position;
140648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // Used within the UI to indicate that a Conversation should be removed from
141648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // the ConversationCursor when executing an update, e.g. the the
142648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // Conversation is no longer in the ConversationList for the current folder,
143648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // that is it's now in some other folder(s)
144ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    public transient boolean localDeleteOnUpdate;
145732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
146e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    // Constituents of convFlags below
147648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // Flag indicating that the item has been deleted, but will continue being
148648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // shown in the list Delete/Archive of a mostly-dead item will NOT propagate
149648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // the delete/archive, but WILL remove the item from the cursor
150e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    public static final int FLAG_MOSTLY_DEAD = 1 << 0;
151e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank
152440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    /** An immutable, empty conversation list */
153440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    public static final Collection<Conversation> EMPTY = Collections.emptyList();
154440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal
155732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
156732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public int describeContents() {
157732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        return 0;
158732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
159732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
160732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
161732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public void writeToParcel(Parcel dest, int flags) {
162732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeLong(id);
163c43bc0a606e41144a780c4f873b5450e0ede0c91Marc Blank        dest.writeParcelable(uri, flags);
164732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeString(subject);
165732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeLong(dateMs);
166732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeString(snippet);
167732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeByte(hasAttachments ? (byte) 1 : 0);
168cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira        dest.writeParcelable(messageListUri, 0);
1694db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeString(senders);
1704db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(numMessages);
1714db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(numDrafts);
1724db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(sendingState);
1734db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(priority);
174c8a994227b9c686d88ee05840544162711a85712Marc Blank        dest.writeByte(read ? (byte) 1 : 0);
175c8a994227b9c686d88ee05840544162711a85712Marc Blank        dest.writeByte(starred ? (byte) 1 : 0);
176ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        dest.writeString(folderList);
177cc8211df898ba9dac17a766b89f28d6e6f0afef0Mindy Pereira        dest.writeString(rawFolders);
17822657529437c160dec072115c5982409306c1313Mindy Pereira        dest.writeInt(convFlags);
17922657529437c160dec072115c5982409306c1313Mindy Pereira        dest.writeInt(personalLevel);
180863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        dest.writeInt(spam ? 1 : 0);
18176b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook        dest.writeInt(phishing ? 1 : 0);
182863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        dest.writeInt(muted ? 1 : 0);
18392939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank        dest.writeInt(color);
184a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank        dest.writeParcelable(accountUri, 0);
18500c67ae6212de5b56c0c94af185061ee2fa36925Mindy Pereira        try {
18600c67ae6212de5b56c0c94af185061ee2fa36925Mindy Pereira            dest.writeString(ConversationInfo.toString(conversationInfo));
18700c67ae6212de5b56c0c94af185061ee2fa36925Mindy Pereira        } catch (JSONException e) {
18800c67ae6212de5b56c0c94af185061ee2fa36925Mindy Pereira            LogUtils.d(LOG_TAG, e, "Error adding conversationinfo to parcel");
18900c67ae6212de5b56c0c94af185061ee2fa36925Mindy Pereira        }
190732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
191732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
192732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    private Conversation(Parcel in) {
193732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        id = in.readLong();
194c43bc0a606e41144a780c4f873b5450e0ede0c91Marc Blank        uri = in.readParcelable(null);
195732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        subject = in.readString();
196732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dateMs = in.readLong();
197732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        snippet = in.readString();
198732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        hasAttachments = (in.readByte() != 0);
199cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira        messageListUri = in.readParcelable(null);
2004db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        senders = in.readString();
2014db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        numMessages = in.readInt();
2024db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        numDrafts = in.readInt();
2034db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        sendingState = in.readInt();
2044db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        priority = in.readInt();
205c8a994227b9c686d88ee05840544162711a85712Marc Blank        read = (in.readByte() != 0);
206c8a994227b9c686d88ee05840544162711a85712Marc Blank        starred = (in.readByte() != 0);
207ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        folderList = in.readString();
208cc8211df898ba9dac17a766b89f28d6e6f0afef0Mindy Pereira        rawFolders = in.readString();
20922657529437c160dec072115c5982409306c1313Mindy Pereira        convFlags = in.readInt();
21022657529437c160dec072115c5982409306c1313Mindy Pereira        personalLevel = in.readInt();
211863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        spam = in.readInt() != 0;
21276b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook        phishing = in.readInt() != 0;
213863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        muted = in.readInt() != 0;
21492939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank        color = in.readInt();
215a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank        accountUri = in.readParcelable(null);
216f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank        position = NO_POSITION;
217ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        localDeleteOnUpdate = false;
21800c67ae6212de5b56c0c94af185061ee2fa36925Mindy Pereira        try {
21900c67ae6212de5b56c0c94af185061ee2fa36925Mindy Pereira            conversationInfo = ConversationInfo.fromString(in.readString());
22000c67ae6212de5b56c0c94af185061ee2fa36925Mindy Pereira        } catch (JSONException e) {
22100c67ae6212de5b56c0c94af185061ee2fa36925Mindy Pereira            LogUtils.d(LOG_TAG, e, "Error retrieving conversation info from parcel");
22200c67ae6212de5b56c0c94af185061ee2fa36925Mindy Pereira        }
223732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
224732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
225732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
226732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public String toString() {
2277dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        return "[conversation id=" + id + ", subject =" + subject + "]";
228732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
229732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
230732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public static final Creator<Conversation> CREATOR = new Creator<Conversation>() {
231732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
232732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        @Override
233732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        public Conversation createFromParcel(Parcel source) {
234732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            return new Conversation(source);
235732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
236732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
237732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        @Override
238732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        public Conversation[] newArray(int size) {
239732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            return new Conversation[size];
240732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
241732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
242732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    };
243732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
244acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira    public static final Uri MOVE_CONVERSATIONS_URI = Uri.parse("content://moveconversations");
245acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira
246ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira    /**
2476c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira     * The columns that need to be updated to change the read state of a conversation.
248ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira     */
249ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira    public static final String[] UPDATE_FOLDER_COLUMNS = new String[] {
250ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira            ConversationColumns.FOLDER_LIST, ConversationColumns.RAW_FOLDERS
251ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira    };
252ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira
253648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    private static final String LOG_TAG = LogTag.getLogTag();
254648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira
255a831b2f1ba6d3c18d5e54563df8bae1f589c4257Mindy Pereira    public Conversation(Cursor cursor) {
256732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        if (cursor != null) {
257732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            id = cursor.getLong(UIProvider.CONVERSATION_ID_COLUMN);
258c43bc0a606e41144a780c4f873b5450e0ede0c91Marc Blank            uri = Uri.parse(cursor.getString(UIProvider.CONVERSATION_URI_COLUMN));
259732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            dateMs = cursor.getLong(UIProvider.CONVERSATION_DATE_RECEIVED_MS_COLUMN);
260732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            subject = cursor.getString(UIProvider.CONVERSATION_SUBJECT_COLUMN);
261374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank            // Don't allow null subject
262374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank            if (subject == null) {
263374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank                subject = "";
264374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank            }
265732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            snippet = cursor.getString(UIProvider.CONVERSATION_SNIPPET_COLUMN);
26687d535fe423d782c3a0343c649330d309976f655Mindy Pereira            hasAttachments = cursor.getInt(UIProvider.CONVERSATION_HAS_ATTACHMENTS_COLUMN) != 0;
267648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            String messageList = cursor.getString(UIProvider.CONVERSATION_MESSAGE_LIST_URI_COLUMN);
2685c765b9c5dd8a9a9421260ba8b46d06073391c73Mindy Pereira            messageListUri = !TextUtils.isEmpty(messageList) ? Uri.parse(messageList) : null;
2694db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            numMessages = cursor.getInt(UIProvider.CONVERSATION_NUM_MESSAGES_COLUMN);
2704db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            numDrafts = cursor.getInt(UIProvider.CONVERSATION_NUM_DRAFTS_COLUMN);
2714db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            sendingState = cursor.getInt(UIProvider.CONVERSATION_SENDING_STATE_COLUMN);
2724db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            priority = cursor.getInt(UIProvider.CONVERSATION_PRIORITY_COLUMN);
27387d535fe423d782c3a0343c649330d309976f655Mindy Pereira            read = cursor.getInt(UIProvider.CONVERSATION_READ_COLUMN) != 0;
27487d535fe423d782c3a0343c649330d309976f655Mindy Pereira            starred = cursor.getInt(UIProvider.CONVERSATION_STARRED_COLUMN) != 0;
275ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank            folderList = cursor.getString(UIProvider.CONVERSATION_FOLDER_LIST_COLUMN);
276cc8211df898ba9dac17a766b89f28d6e6f0afef0Mindy Pereira            rawFolders = cursor.getString(UIProvider.CONVERSATION_RAW_FOLDERS_COLUMN);
27722657529437c160dec072115c5982409306c1313Mindy Pereira            convFlags = cursor.getInt(UIProvider.CONVERSATION_FLAGS_COLUMN);
27822657529437c160dec072115c5982409306c1313Mindy Pereira            personalLevel = cursor.getInt(UIProvider.CONVERSATION_PERSONAL_LEVEL_COLUMN);
279863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira            spam = cursor.getInt(UIProvider.CONVERSATION_IS_SPAM_COLUMN) != 0;
28076b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook            phishing = cursor.getInt(UIProvider.CONVERSATION_IS_PHISHING_COLUMN) != 0;
281863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira            muted = cursor.getInt(UIProvider.CONVERSATION_MUTED_COLUMN) != 0;
28292939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank            color = cursor.getInt(UIProvider.CONVERSATION_COLOR_COLUMN);
283a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank            String account = cursor.getString(UIProvider.CONVERSATION_ACCOUNT_URI_COLUMN);
284a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank            accountUri = !TextUtils.isEmpty(account) ? Uri.parse(account) : null;
285f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank            position = NO_POSITION;
286ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank            localDeleteOnUpdate = false;
287648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            senders = cursor.getString(UIProvider.CONVERSATION_SENDER_INFO_COLUMN);
288648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            try {
289648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira                conversationInfo = ConversationInfo.fromString(cursor
290648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira                        .getString(UIProvider.CONVERSATION_INFO_COLUMN));
291648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            } catch (JSONException e) {
292648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira                LogUtils.w(LOG_TAG, e,
293648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira                        "Unable to instantiate ConversationInfo. Try to continue anyway");
294648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            }
295732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
296732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
297732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
298bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook    public Conversation() {
299ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook    }
300ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook
301863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira    public static Conversation create(long id, Uri uri, String subject, long dateMs,
302863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira            String snippet, boolean hasAttachment, Uri messageListUri, String senders,
303863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira            int numMessages, int numDrafts, int sendingState, int priority, boolean read,
304863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira            boolean starred, String folderList, String rawFolders, int convFlags,
30576b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook            int personalLevel, boolean spam, boolean phishing, boolean muted, Uri accountUri) {
306ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook
307ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        final Conversation conversation = new Conversation();
308ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook
309ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.id = id;
310ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.uri = uri;
311ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.subject = subject;
312ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.dateMs = dateMs;
313ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.snippet = snippet;
314ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.hasAttachments = hasAttachment;
315ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.messageListUri = messageListUri;
316ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.senders = senders;
317ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.numMessages = numMessages;
318ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.numDrafts = numDrafts;
319ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.sendingState = sendingState;
320ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.priority = priority;
321ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.read = read;
322ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.starred = starred;
323ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.folderList = folderList;
324ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.rawFolders = rawFolders;
325ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.convFlags = convFlags;
326ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.personalLevel = personalLevel;
327863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        conversation.spam = spam;
32876b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook        conversation.phishing = phishing;
329863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        conversation.muted = muted;
33092939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank        conversation.color = 0;
331a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank        conversation.accountUri = accountUri;
332ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        return conversation;
333ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook    }
334ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook
335e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    @Override
336e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    public boolean equals(Object o) {
3373c9bcef43b4f103697034abbf2eab99111e8d987Marc Blank        if (o instanceof Conversation) {
338648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            Conversation conv = (Conversation) o;
3393c9bcef43b4f103697034abbf2eab99111e8d987Marc Blank            return conv.uri.equals(uri);
3403c9bcef43b4f103697034abbf2eab99111e8d987Marc Blank        }
3413c9bcef43b4f103697034abbf2eab99111e8d987Marc Blank        return false;
342e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    }
343e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank
344e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    @Override
345e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    public int hashCode() {
346e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank        return uri.hashCode();
347e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    }
348e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank
3497f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    /**
3507f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira     * Get if this conversation is marked as high priority.
3517f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira     */
3527f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    public boolean isImportant() {
35322657529437c160dec072115c5982409306c1313Mindy Pereira        return priority == UIProvider.ConversationPriority.IMPORTANT;
3547f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    }
3557f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira
356e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    /**
357e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank     * Get if this conversation is mostly dead
358e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank     */
359e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    public boolean isMostlyDead() {
360e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank        return (convFlags & FLAG_MOSTLY_DEAD) != 0;
361e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    }
362440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal
363440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    /**
364648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * Returns true if the URI of the conversation specified as the needle was
365648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * found in the collection of conversations specified as the haystack. False
366648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * otherwise. This method is safe to call with nullarguments.
367648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     *
368d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal     * @param haystack
369d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal     * @param needle
370d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal     * @return true if the needle was found in the haystack, false otherwise.
371d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal     */
372d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal    public final static boolean contains(Collection<Conversation> haystack, Conversation needle) {
373d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        // If the haystack is empty, it cannot contain anything.
374d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        if (haystack == null || haystack.size() <= 0) {
375d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal            return false;
376d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        }
377d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        // The null folder exists everywhere.
378d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        if (needle == null) {
379d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal            return true;
380d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        }
3817dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        final long toFind = needle.id;
382d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        for (final Conversation c : haystack) {
3837dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal            if (toFind == c.id) {
384d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal                return true;
385d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal            }
386d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        }
387d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        return false;
388d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal    }
389d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal
390d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal    /**
391648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * Returns a collection of a single conversation. This method always returns
392648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * a valid collection even if the input conversation is null.
393648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     *
394440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal     * @param in a conversation, possibly null.
395440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal     * @return a collection of the conversation.
396440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal     */
397440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    public static Collection<Conversation> listOf(Conversation in) {
398440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal        final Collection<Conversation> target = (in == null) ? EMPTY : ImmutableList.of(in);
399440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal        return target;
400440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    }
4017dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal
4027dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal    /**
403aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira     * Get the snippet for this conversation. Masks that it may come from
404aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira     * conversation info or the original deprecated snippet string.
405aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira     */
406aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira    public String getSnippet() {
407d97782206889a5508279b75cce19d7c0fb8a3bcaMindy Pereira        return conversationInfo != null && !TextUtils.isEmpty(conversationInfo.firstSnippet) ?
408d97782206889a5508279b75cce19d7c0fb8a3bcaMindy Pereira                conversationInfo.firstSnippet : snippet;
409aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira    }
410aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira
411aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira    /**
4127dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     * Create a human-readable string of all the conversations
413648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     *
4147dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     * @param collection Any collection of conversations
4157dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     * @return string with a human readable representation of the conversations.
4167dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     */
4177dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal    public static String toString(Collection<Conversation> collection) {
4187dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        final StringBuilder out = new StringBuilder(collection.size() + " conversations:");
4197dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        int count = 0;
4207dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        for (final Conversation c : collection) {
4217dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal            count++;
422648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            // Indent the conversations to make them easy to read in debug
423648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            // output.
4247dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal            out.append("      " + count + ": " + c.toString() + "\n");
4257dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        }
4267dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        return out.toString();
4277dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal    }
428648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira}
429