Conversation.java revision 648df3f0b0ebcd3c4adf907d70ff0938e5dfc78f
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     */
58732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public String snippet;
59e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
60e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#HAS_ATTACHMENTS
61e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
62732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public boolean hasAttachments;
63e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
64e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#MESSAGE_LIST_URI
65e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
66cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira    public Uri messageListUri;
67e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
68e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#SENDER_INFO
69e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
70648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    @Deprecated
714db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public String senders;
72e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
73e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#NUM_MESSAGES
74e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
754db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int numMessages;
76e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
77e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#NUM_DRAFTS
78e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
794db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int numDrafts;
80e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
81e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#SENDING_STATE
82e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
834db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int sendingState;
84e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
85e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#PRIORITY
86e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
874db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int priority;
88e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
89e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#READ
90e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
91c8a994227b9c686d88ee05840544162711a85712Marc Blank    public boolean read;
92e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
93e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#STARRED
94e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
95c8a994227b9c686d88ee05840544162711a85712Marc Blank    public boolean starred;
96e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
97e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#FOLDER_LIST
98e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
99ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    public String folderList;
100e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
101e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#RAW_FOLDERS
102e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
103cc8211df898ba9dac17a766b89f28d6e6f0afef0Mindy Pereira    public String rawFolders;
104e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
105e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#FLAGS
106e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
10722657529437c160dec072115c5982409306c1313Mindy Pereira    public int convFlags;
108e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
109e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#PERSONAL_LEVEL
110e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
11122657529437c160dec072115c5982409306c1313Mindy Pereira    public int personalLevel;
112e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
113e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#SPAM
114e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
115863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira    public boolean spam;
116e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
117e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#MUTED
118e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
119863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira    public boolean muted;
120e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
12176b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook     * @see UIProvider.ConversationColumns#PHISHING
12276b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook     */
12376b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook    public boolean phishing;
12476b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook    /**
125e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#COLOR
126e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
12792939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank    public int color;
128e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
129e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.ConversationColumns#ACCOUNT_URI
130e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
131a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank    public Uri accountUri;
132648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    /**
133648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * @see UIProvider.ConversationColumns#CONVERSATION_INFO
134648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     */
135648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    public ConversationInfo conversationInfo;
13622657529437c160dec072115c5982409306c1313Mindy Pereira
137ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    // Used within the UI to indicate the adapter position of this conversation
138f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank    public transient int position;
139648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // Used within the UI to indicate that a Conversation should be removed from
140648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // the ConversationCursor when executing an update, e.g. the the
141648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // Conversation is no longer in the ConversationList for the current folder,
142648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // that is it's now in some other folder(s)
143ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    public transient boolean localDeleteOnUpdate;
144732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
145e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    // Constituents of convFlags below
146648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // Flag indicating that the item has been deleted, but will continue being
147648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // shown in the list Delete/Archive of a mostly-dead item will NOT propagate
148648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    // the delete/archive, but WILL remove the item from the cursor
149e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    public static final int FLAG_MOSTLY_DEAD = 1 << 0;
150e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank
151440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    /** An immutable, empty conversation list */
152440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    public static final Collection<Conversation> EMPTY = Collections.emptyList();
153440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal
154732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
155732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public int describeContents() {
156732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        return 0;
157732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
158732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
159732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
160732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public void writeToParcel(Parcel dest, int flags) {
161732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeLong(id);
162c43bc0a606e41144a780c4f873b5450e0ede0c91Marc Blank        dest.writeParcelable(uri, flags);
163732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeString(subject);
164732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeLong(dateMs);
165732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeString(snippet);
166732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeByte(hasAttachments ? (byte) 1 : 0);
167cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira        dest.writeParcelable(messageListUri, 0);
1684db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeString(senders);
1694db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(numMessages);
1704db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(numDrafts);
1714db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(sendingState);
1724db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(priority);
173c8a994227b9c686d88ee05840544162711a85712Marc Blank        dest.writeByte(read ? (byte) 1 : 0);
174c8a994227b9c686d88ee05840544162711a85712Marc Blank        dest.writeByte(starred ? (byte) 1 : 0);
175ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        dest.writeString(folderList);
176cc8211df898ba9dac17a766b89f28d6e6f0afef0Mindy Pereira        dest.writeString(rawFolders);
17722657529437c160dec072115c5982409306c1313Mindy Pereira        dest.writeInt(convFlags);
17822657529437c160dec072115c5982409306c1313Mindy Pereira        dest.writeInt(personalLevel);
179863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        dest.writeInt(spam ? 1 : 0);
18076b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook        dest.writeInt(phishing ? 1 : 0);
181863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        dest.writeInt(muted ? 1 : 0);
18292939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank        dest.writeInt(color);
183a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank        dest.writeParcelable(accountUri, 0);
184732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
185732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
186732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    private Conversation(Parcel in) {
187732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        id = in.readLong();
188c43bc0a606e41144a780c4f873b5450e0ede0c91Marc Blank        uri = in.readParcelable(null);
189732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        subject = in.readString();
190732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dateMs = in.readLong();
191732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        snippet = in.readString();
192732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        hasAttachments = (in.readByte() != 0);
193cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira        messageListUri = in.readParcelable(null);
1944db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        senders = in.readString();
1954db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        numMessages = in.readInt();
1964db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        numDrafts = in.readInt();
1974db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        sendingState = in.readInt();
1984db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        priority = in.readInt();
199c8a994227b9c686d88ee05840544162711a85712Marc Blank        read = (in.readByte() != 0);
200c8a994227b9c686d88ee05840544162711a85712Marc Blank        starred = (in.readByte() != 0);
201ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        folderList = in.readString();
202cc8211df898ba9dac17a766b89f28d6e6f0afef0Mindy Pereira        rawFolders = in.readString();
20322657529437c160dec072115c5982409306c1313Mindy Pereira        convFlags = in.readInt();
20422657529437c160dec072115c5982409306c1313Mindy Pereira        personalLevel = in.readInt();
205863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        spam = in.readInt() != 0;
20676b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook        phishing = in.readInt() != 0;
207863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        muted = in.readInt() != 0;
20892939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank        color = in.readInt();
209a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank        accountUri = in.readParcelable(null);
210f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank        position = NO_POSITION;
211ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        localDeleteOnUpdate = false;
212732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
213732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
214732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
215732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public String toString() {
2167dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        return "[conversation id=" + id + ", subject =" + subject + "]";
217732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
218732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
219732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public static final Creator<Conversation> CREATOR = new Creator<Conversation>() {
220732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
221732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        @Override
222732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        public Conversation createFromParcel(Parcel source) {
223732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            return new Conversation(source);
224732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
225732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
226732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        @Override
227732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        public Conversation[] newArray(int size) {
228732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            return new Conversation[size];
229732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
230732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
231732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    };
232732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
233acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira    public static final Uri MOVE_CONVERSATIONS_URI = Uri.parse("content://moveconversations");
234acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira
235ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira    /**
236648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * The columns that need to be updated to change the folders for a
237648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * conversation.
238ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira     */
239ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira    public static final String[] UPDATE_FOLDER_COLUMNS = new String[] {
240ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira            ConversationColumns.FOLDER_LIST, ConversationColumns.RAW_FOLDERS
241ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira    };
242ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira
243648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira    private static final String LOG_TAG = LogTag.getLogTag();
244648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira
245a831b2f1ba6d3c18d5e54563df8bae1f589c4257Mindy Pereira    public Conversation(Cursor cursor) {
246732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        if (cursor != null) {
247732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            id = cursor.getLong(UIProvider.CONVERSATION_ID_COLUMN);
248c43bc0a606e41144a780c4f873b5450e0ede0c91Marc Blank            uri = Uri.parse(cursor.getString(UIProvider.CONVERSATION_URI_COLUMN));
249732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            dateMs = cursor.getLong(UIProvider.CONVERSATION_DATE_RECEIVED_MS_COLUMN);
250732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            subject = cursor.getString(UIProvider.CONVERSATION_SUBJECT_COLUMN);
251374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank            // Don't allow null subject
252374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank            if (subject == null) {
253374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank                subject = "";
254374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank            }
255732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            snippet = cursor.getString(UIProvider.CONVERSATION_SNIPPET_COLUMN);
25687d535fe423d782c3a0343c649330d309976f655Mindy Pereira            hasAttachments = cursor.getInt(UIProvider.CONVERSATION_HAS_ATTACHMENTS_COLUMN) != 0;
257648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            String messageList = cursor.getString(UIProvider.CONVERSATION_MESSAGE_LIST_URI_COLUMN);
2585c765b9c5dd8a9a9421260ba8b46d06073391c73Mindy Pereira            messageListUri = !TextUtils.isEmpty(messageList) ? Uri.parse(messageList) : null;
2594db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            numMessages = cursor.getInt(UIProvider.CONVERSATION_NUM_MESSAGES_COLUMN);
2604db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            numDrafts = cursor.getInt(UIProvider.CONVERSATION_NUM_DRAFTS_COLUMN);
2614db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            sendingState = cursor.getInt(UIProvider.CONVERSATION_SENDING_STATE_COLUMN);
2624db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            priority = cursor.getInt(UIProvider.CONVERSATION_PRIORITY_COLUMN);
26387d535fe423d782c3a0343c649330d309976f655Mindy Pereira            read = cursor.getInt(UIProvider.CONVERSATION_READ_COLUMN) != 0;
26487d535fe423d782c3a0343c649330d309976f655Mindy Pereira            starred = cursor.getInt(UIProvider.CONVERSATION_STARRED_COLUMN) != 0;
265ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank            folderList = cursor.getString(UIProvider.CONVERSATION_FOLDER_LIST_COLUMN);
266cc8211df898ba9dac17a766b89f28d6e6f0afef0Mindy Pereira            rawFolders = cursor.getString(UIProvider.CONVERSATION_RAW_FOLDERS_COLUMN);
26722657529437c160dec072115c5982409306c1313Mindy Pereira            convFlags = cursor.getInt(UIProvider.CONVERSATION_FLAGS_COLUMN);
26822657529437c160dec072115c5982409306c1313Mindy Pereira            personalLevel = cursor.getInt(UIProvider.CONVERSATION_PERSONAL_LEVEL_COLUMN);
269863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira            spam = cursor.getInt(UIProvider.CONVERSATION_IS_SPAM_COLUMN) != 0;
27076b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook            phishing = cursor.getInt(UIProvider.CONVERSATION_IS_PHISHING_COLUMN) != 0;
271863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira            muted = cursor.getInt(UIProvider.CONVERSATION_MUTED_COLUMN) != 0;
27292939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank            color = cursor.getInt(UIProvider.CONVERSATION_COLOR_COLUMN);
273a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank            String account = cursor.getString(UIProvider.CONVERSATION_ACCOUNT_URI_COLUMN);
274a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank            accountUri = !TextUtils.isEmpty(account) ? Uri.parse(account) : null;
275f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank            position = NO_POSITION;
276ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank            localDeleteOnUpdate = false;
277648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            senders = cursor.getString(UIProvider.CONVERSATION_SENDER_INFO_COLUMN);
278648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            try {
279648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira                conversationInfo = ConversationInfo.fromString(cursor
280648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira                        .getString(UIProvider.CONVERSATION_INFO_COLUMN));
281648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            } catch (JSONException e) {
282648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira                LogUtils.w(LOG_TAG, e,
283648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira                        "Unable to instantiate ConversationInfo. Try to continue anyway");
284648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            }
285732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
286732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
287732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
288bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook    public Conversation() {
289ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook    }
290ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook
291863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira    public static Conversation create(long id, Uri uri, String subject, long dateMs,
292863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira            String snippet, boolean hasAttachment, Uri messageListUri, String senders,
293863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira            int numMessages, int numDrafts, int sendingState, int priority, boolean read,
294863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira            boolean starred, String folderList, String rawFolders, int convFlags,
29576b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook            int personalLevel, boolean spam, boolean phishing, boolean muted, Uri accountUri) {
296ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook
297ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        final Conversation conversation = new Conversation();
298ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook
299ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.id = id;
300ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.uri = uri;
301ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.subject = subject;
302ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.dateMs = dateMs;
303ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.snippet = snippet;
304ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.hasAttachments = hasAttachment;
305ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.messageListUri = messageListUri;
306ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.senders = senders;
307ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.numMessages = numMessages;
308ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.numDrafts = numDrafts;
309ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.sendingState = sendingState;
310ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.priority = priority;
311ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.read = read;
312ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.starred = starred;
313ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.folderList = folderList;
314ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.rawFolders = rawFolders;
315ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.convFlags = convFlags;
316ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        conversation.personalLevel = personalLevel;
317863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        conversation.spam = spam;
31876b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook        conversation.phishing = phishing;
319863e44160d9175023d30e7e225ecb69ad3892eecMindy Pereira        conversation.muted = muted;
32092939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank        conversation.color = 0;
321a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank        conversation.accountUri = accountUri;
322ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook        return conversation;
323ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook    }
324ff5c757ed2bcf7004a70b0675382ef894196558dPaul Westbrook
325e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    @Override
326e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    public boolean equals(Object o) {
3273c9bcef43b4f103697034abbf2eab99111e8d987Marc Blank        if (o instanceof Conversation) {
328648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            Conversation conv = (Conversation) o;
3293c9bcef43b4f103697034abbf2eab99111e8d987Marc Blank            return conv.uri.equals(uri);
3303c9bcef43b4f103697034abbf2eab99111e8d987Marc Blank        }
3313c9bcef43b4f103697034abbf2eab99111e8d987Marc Blank        return false;
332e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    }
333e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank
334e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    @Override
335e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    public int hashCode() {
336e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank        return uri.hashCode();
337e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    }
338e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank
3397f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    /**
3407f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira     * Get if this conversation is marked as high priority.
3417f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira     */
3427f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    public boolean isImportant() {
34322657529437c160dec072115c5982409306c1313Mindy Pereira        return priority == UIProvider.ConversationPriority.IMPORTANT;
3447f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    }
3457f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira
346e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    /**
347e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank     * Get if this conversation is mostly dead
348e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank     */
349e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    public boolean isMostlyDead() {
350e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank        return (convFlags & FLAG_MOSTLY_DEAD) != 0;
351e1d1b07cdb0026097eb80f6c2912a16353aacec1Marc Blank    }
352440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal
353440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    /**
354648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * Returns true if the URI of the conversation specified as the needle was
355648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * found in the collection of conversations specified as the haystack. False
356648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * otherwise. This method is safe to call with nullarguments.
357648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     *
358d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal     * @param haystack
359d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal     * @param needle
360d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal     * @return true if the needle was found in the haystack, false otherwise.
361d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal     */
362d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal    public final static boolean contains(Collection<Conversation> haystack, Conversation needle) {
363d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        // If the haystack is empty, it cannot contain anything.
364d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        if (haystack == null || haystack.size() <= 0) {
365d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal            return false;
366d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        }
367d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        // The null folder exists everywhere.
368d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        if (needle == null) {
369d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal            return true;
370d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        }
3717dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        final long toFind = needle.id;
372d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        for (final Conversation c : haystack) {
3737dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal            if (toFind == c.id) {
374d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal                return true;
375d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal            }
376d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        }
377d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal        return false;
378d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal    }
379d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal
380d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal    /**
381648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * Returns a collection of a single conversation. This method always returns
382648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     * a valid collection even if the input conversation is null.
383648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     *
384440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal     * @param in a conversation, possibly null.
385440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal     * @return a collection of the conversation.
386440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal     */
387440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    public static Collection<Conversation> listOf(Conversation in) {
388440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal        final Collection<Conversation> target = (in == null) ? EMPTY : ImmutableList.of(in);
389440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal        return target;
390440fe79194314b25ef5829702494735ce2f1e2e8Vikram Aggarwal    }
3917dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal
3927dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal    /**
3937dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     * Create a human-readable string of all the conversations
394648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira     *
3957dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     * @param collection Any collection of conversations
3967dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     * @return string with a human readable representation of the conversations.
3977dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     */
3987dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal    public static String toString(Collection<Conversation> collection) {
3997dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        final StringBuilder out = new StringBuilder(collection.size() + " conversations:");
4007dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        int count = 0;
4017dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        for (final Conversation c : collection) {
4027dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal            count++;
403648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            // Indent the conversations to make them easy to read in debug
404648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira            // output.
4057dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal            out.append("      " + count + ": " + c.toString() + "\n");
4067dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        }
4077dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        return out.toString();
4087dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal    }
409648df3f0b0ebcd3c4adf907d70ff0938e5dfc78fMindy Pereira}
410