Conversation.java revision 22657529437c160dec072115c5982409306c1313
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
198d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blankimport android.content.ContentProviderClient;
20c8a994227b9c686d88ee05840544162711a85712Marc Blankimport android.content.ContentValues;
21c8a994227b9c686d88ee05840544162711a85712Marc Blankimport android.content.Context;
22732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport android.database.Cursor;
23732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport android.net.Uri;
24732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport android.os.Parcel;
25732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport android.os.Parcelable;
265c765b9c5dd8a9a9421260ba8b46d06073391c73Mindy Pereiraimport android.text.TextUtils;
27732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
288d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blankimport com.android.mail.browse.ConversationCursor.ConversationOperation;
298d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blankimport com.android.mail.browse.ConversationCursor.ConversationProvider;
3017a9cde3b0e28fc98fdeda19de81e18056eb09dbAndy Huangimport com.android.mail.providers.UIProvider.ConversationColumns;
318d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank
328d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blankimport java.util.ArrayList;
338d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blankimport java.util.Collection;
348d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank
35732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangpublic class Conversation implements Parcelable {
36f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank    public static final int NO_POSITION = -1;
37732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
38732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public long id;
39c43bc0a606e41144a780c4f873b5450e0ede0c91Marc Blank    public Uri uri;
40732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public String subject;
41732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public long dateMs;
42732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public String snippet;
43732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public boolean hasAttachments;
44cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira    public Uri messageListUri;
454db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public String senders;
464db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int numMessages;
474db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int numDrafts;
484db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int sendingState;
494db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int priority;
50c8a994227b9c686d88ee05840544162711a85712Marc Blank    public boolean read;
51c8a994227b9c686d88ee05840544162711a85712Marc Blank    public boolean starred;
52ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    public String folderList;
53cc8211df898ba9dac17a766b89f28d6e6f0afef0Mindy Pereira    public String rawFolders;
5422657529437c160dec072115c5982409306c1313Mindy Pereira    public int convFlags;
5522657529437c160dec072115c5982409306c1313Mindy Pereira    public int personalLevel;
5622657529437c160dec072115c5982409306c1313Mindy Pereira
57ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    // Used within the UI to indicate the adapter position of this conversation
58f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank    public transient int position;
59ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    // Used within the UI to indicate that a Conversation should be removed from the
60ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    // ConversationCursor when executing an update, e.g. the the Conversation is no longer
61ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    // in the ConversationList for the current folder, that is it's now in some other folder(s)
62ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    public transient boolean localDeleteOnUpdate;
63732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
64732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
65732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public int describeContents() {
66732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        return 0;
67732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
68732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
69732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
70732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public void writeToParcel(Parcel dest, int flags) {
71732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeLong(id);
72c43bc0a606e41144a780c4f873b5450e0ede0c91Marc Blank        dest.writeParcelable(uri, flags);
73732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeString(subject);
74732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeLong(dateMs);
75732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeString(snippet);
76732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeByte(hasAttachments ? (byte) 1 : 0);
77cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira        dest.writeParcelable(messageListUri, 0);
784db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeString(senders);
794db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(numMessages);
804db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(numDrafts);
814db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(sendingState);
824db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(priority);
83c8a994227b9c686d88ee05840544162711a85712Marc Blank        dest.writeByte(read ? (byte) 1 : 0);
84c8a994227b9c686d88ee05840544162711a85712Marc Blank        dest.writeByte(starred ? (byte) 1 : 0);
85ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        dest.writeString(folderList);
86cc8211df898ba9dac17a766b89f28d6e6f0afef0Mindy Pereira        dest.writeString(rawFolders);
8722657529437c160dec072115c5982409306c1313Mindy Pereira        dest.writeInt(convFlags);
8822657529437c160dec072115c5982409306c1313Mindy Pereira        dest.writeInt(personalLevel);
89732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
90732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
91732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    private Conversation(Parcel in) {
92732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        id = in.readLong();
93c43bc0a606e41144a780c4f873b5450e0ede0c91Marc Blank        uri = in.readParcelable(null);
94732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        subject = in.readString();
95732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dateMs = in.readLong();
96732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        snippet = in.readString();
97732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        hasAttachments = (in.readByte() != 0);
98cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira        messageListUri = in.readParcelable(null);
994db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        senders = in.readString();
1004db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        numMessages = in.readInt();
1014db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        numDrafts = in.readInt();
1024db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        sendingState = in.readInt();
1034db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        priority = in.readInt();
104c8a994227b9c686d88ee05840544162711a85712Marc Blank        read = (in.readByte() != 0);
105c8a994227b9c686d88ee05840544162711a85712Marc Blank        starred = (in.readByte() != 0);
106ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        folderList = in.readString();
107cc8211df898ba9dac17a766b89f28d6e6f0afef0Mindy Pereira        rawFolders = in.readString();
10822657529437c160dec072115c5982409306c1313Mindy Pereira        convFlags = in.readInt();
10922657529437c160dec072115c5982409306c1313Mindy Pereira        personalLevel = in.readInt();
110f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank        position = NO_POSITION;
111ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        localDeleteOnUpdate = false;
112732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
113732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
114732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
115732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public String toString() {
116732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        return "[conversation id=" + id + "]";
117732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
118732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
119732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public static final Creator<Conversation> CREATOR = new Creator<Conversation>() {
120732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
121732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        @Override
122732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        public Conversation createFromParcel(Parcel source) {
123732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            return new Conversation(source);
124732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
125732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
126732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        @Override
127732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        public Conversation[] newArray(int size) {
128732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            return new Conversation[size];
129732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
130732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
131732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    };
132732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
133a831b2f1ba6d3c18d5e54563df8bae1f589c4257Mindy Pereira    public Conversation(Cursor cursor) {
134732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        if (cursor != null) {
135732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            id = cursor.getLong(UIProvider.CONVERSATION_ID_COLUMN);
136c43bc0a606e41144a780c4f873b5450e0ede0c91Marc Blank            uri = Uri.parse(cursor.getString(UIProvider.CONVERSATION_URI_COLUMN));
137732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            dateMs = cursor.getLong(UIProvider.CONVERSATION_DATE_RECEIVED_MS_COLUMN);
138732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            subject = cursor.getString(UIProvider.CONVERSATION_SUBJECT_COLUMN);
139374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank            // Don't allow null subject
140374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank            if (subject == null) {
141374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank                subject = "";
142374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank            }
143732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            snippet = cursor.getString(UIProvider.CONVERSATION_SNIPPET_COLUMN);
144c8a994227b9c686d88ee05840544162711a85712Marc Blank            hasAttachments = cursor.getInt(UIProvider.CONVERSATION_HAS_ATTACHMENTS_COLUMN) == 1;
1455c765b9c5dd8a9a9421260ba8b46d06073391c73Mindy Pereira            String messageList = cursor
1465c765b9c5dd8a9a9421260ba8b46d06073391c73Mindy Pereira                    .getString(UIProvider.CONVERSATION_MESSAGE_LIST_URI_COLUMN);
1475c765b9c5dd8a9a9421260ba8b46d06073391c73Mindy Pereira            messageListUri = !TextUtils.isEmpty(messageList) ? Uri.parse(messageList) : null;
1484db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            senders = cursor.getString(UIProvider.CONVERSATION_SENDER_INFO_COLUMN);
1494db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            numMessages = cursor.getInt(UIProvider.CONVERSATION_NUM_MESSAGES_COLUMN);
1504db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            numDrafts = cursor.getInt(UIProvider.CONVERSATION_NUM_DRAFTS_COLUMN);
1514db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            sendingState = cursor.getInt(UIProvider.CONVERSATION_SENDING_STATE_COLUMN);
1524db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            priority = cursor.getInt(UIProvider.CONVERSATION_PRIORITY_COLUMN);
153c8a994227b9c686d88ee05840544162711a85712Marc Blank            read = cursor.getInt(UIProvider.CONVERSATION_READ_COLUMN) == 1;
154c8a994227b9c686d88ee05840544162711a85712Marc Blank            starred = cursor.getInt(UIProvider.CONVERSATION_STARRED_COLUMN) == 1;
155ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank            folderList = cursor.getString(UIProvider.CONVERSATION_FOLDER_LIST_COLUMN);
156cc8211df898ba9dac17a766b89f28d6e6f0afef0Mindy Pereira            rawFolders = cursor.getString(UIProvider.CONVERSATION_RAW_FOLDERS_COLUMN);
15722657529437c160dec072115c5982409306c1313Mindy Pereira            convFlags = cursor.getInt(UIProvider.CONVERSATION_FLAGS_COLUMN);
15822657529437c160dec072115c5982409306c1313Mindy Pereira            personalLevel = cursor.getInt(UIProvider.CONVERSATION_PERSONAL_LEVEL_COLUMN);
159f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank            position = NO_POSITION;
160ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank            localDeleteOnUpdate = false;
161732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
162732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
163732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
1647f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    /**
1657f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira     * Get if this conversation is marked as high priority.
1667f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira     */
1677f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    public boolean isImportant() {
16822657529437c160dec072115c5982409306c1313Mindy Pereira        return priority == UIProvider.ConversationPriority.IMPORTANT;
1697f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    }
1707f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira
171c8a994227b9c686d88ee05840544162711a85712Marc Blank    // Below are methods that update Conversation data (update/delete)
172c8a994227b9c686d88ee05840544162711a85712Marc Blank
1738d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    /**
1747f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira     * Update an integer column for a single conversation (see updateBoolean below)
1757f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira     */
1767f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    public int updateInt(Context context, String columnName, int value) {
1777f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira        ArrayList<Conversation> conversations = new ArrayList<Conversation>();
1787f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira        conversations.add(this);
1797f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira        return updateInt(context, conversations, columnName, value);
1807f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    }
1817f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira
1827f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    /**
1837f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira     * Update an integer column for a group of conversations (see updateValues below)
1847f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira     */
1857f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    public static int updateInt(Context context, Collection<Conversation> conversations,
1867f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira            String columnName, int value) {
1877f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira        ContentValues cv = new ContentValues();
1887f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira        cv.put(columnName, value);
1897f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira        return updateValues(context, conversations, cv);
1907f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    }
1917f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira
1927f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira    /**
193ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank     * Update a boolean column for a single conversation (see updateBoolean below)
1948d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     */
195dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank    public int updateBoolean(Context context, String columnName, boolean value) {
196dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank        ArrayList<Conversation> conversations = new ArrayList<Conversation>();
197dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank        conversations.add(this);
198dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank        return updateBoolean(context, conversations, columnName, value);
199c8a994227b9c686d88ee05840544162711a85712Marc Blank    }
200c8a994227b9c686d88ee05840544162711a85712Marc Blank
2018d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    /**
202ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank     * Update a string column for a group of conversations (see updateValues below)
203ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank     */
204ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    public static int updateBoolean(Context context, Collection<Conversation> conversations,
205ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank            String columnName, boolean value) {
206ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        ContentValues cv = new ContentValues();
207ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        cv.put(columnName, value);
208ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        return updateValues(context, conversations, cv);
209ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    }
210ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank
211ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    /**
212ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank     * Update a string column for a single conversation (see updateString below)
213ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank     */
214ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    public int updateString(Context context, String columnName, String value) {
215ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        ArrayList<Conversation> conversations = new ArrayList<Conversation>();
216ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        conversations.add(this);
217ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        return updateString(context, conversations, columnName, value);
218ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    }
219ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank
220ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    /**
221ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank     * Update a string column for a group of conversations (see updateValues below)
222ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank     */
223ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    public static int updateString(Context context, Collection<Conversation> conversations,
224ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank            String columnName, String value) {
225ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        ContentValues cv = new ContentValues();
226ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        cv.put(columnName, value);
227ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank        return updateValues(context, conversations, cv);
228ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    }
229ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank
230ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    /**
2318d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * Update a boolean column for a group of conversations, immediately in the UI and in a single
2328d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * transaction in the underlying provider
2338d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param conversations a collection of conversations
2348d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param context the caller's context
2358d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param columnName the column to update
2368d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param value the new value
2371b9efd9beb715927e0db7b138ddbb2925bc2c06fMarc Blank     * @return the sequence number of the operation (for undo)
2388d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     */
239ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank    private static int updateValues(Context context, Collection<Conversation> conversations,
240ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank            ContentValues values) {
2418d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        ArrayList<ConversationOperation> ops = new ArrayList<ConversationOperation>();
2428d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        for (Conversation conv: conversations) {
2438d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank            ConversationOperation op =
244ce53818e1e185a845bd2f7f601c20e7085b40725Marc Blank                    new ConversationOperation(ConversationOperation.UPDATE, conv, values);
2458d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank            ops.add(op);
2468d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        }
2471b9efd9beb715927e0db7b138ddbb2925bc2c06fMarc Blank        return apply(context, ops);
2488d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    }
2498d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank
2508d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    /**
2518d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * Delete a single conversation
2528d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param context the caller's context
253dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank     * @return the sequence number of the operation (for undo)
2548d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     */
255dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank    public int delete(Context context) {
256dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank        ArrayList<Conversation> conversations = new ArrayList<Conversation>();
257dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank        conversations.add(this);
258dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank        return delete(context, conversations);
259c8a994227b9c686d88ee05840544162711a85712Marc Blank    }
2608d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank
2618d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    /**
26217a9cde3b0e28fc98fdeda19de81e18056eb09dbAndy Huang     * Mark a single conversation read/unread.
26317a9cde3b0e28fc98fdeda19de81e18056eb09dbAndy Huang     * @param context the caller's context
26417a9cde3b0e28fc98fdeda19de81e18056eb09dbAndy Huang     * @param read true for read, false for unread
26517a9cde3b0e28fc98fdeda19de81e18056eb09dbAndy Huang     * @return the sequence number of the operation (for undo)
26617a9cde3b0e28fc98fdeda19de81e18056eb09dbAndy Huang     */
26717a9cde3b0e28fc98fdeda19de81e18056eb09dbAndy Huang    public int markRead(Context context, boolean read) {
26817a9cde3b0e28fc98fdeda19de81e18056eb09dbAndy Huang        return updateBoolean(context, ConversationColumns.READ, read);
26917a9cde3b0e28fc98fdeda19de81e18056eb09dbAndy Huang    }
27017a9cde3b0e28fc98fdeda19de81e18056eb09dbAndy Huang
27117a9cde3b0e28fc98fdeda19de81e18056eb09dbAndy Huang    /**
2728d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * Delete a group of conversations immediately in the UI and in a single transaction in the
2738d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * underlying provider
2748d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param context the caller's context
2758d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param conversations a collection of conversations
2761b9efd9beb715927e0db7b138ddbb2925bc2c06fMarc Blank     * @return the sequence number of the operation (for undo)
2778d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     */
2781b9efd9beb715927e0db7b138ddbb2925bc2c06fMarc Blank    public static int delete(Context context, Collection<Conversation> conversations) {
2798d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        ArrayList<ConversationOperation> ops = new ArrayList<ConversationOperation>();
2808d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        for (Conversation conv: conversations) {
2818d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank            ConversationOperation op =
282f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank                    new ConversationOperation(ConversationOperation.DELETE, conv);
2838d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank            ops.add(op);
2848d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        }
2851b9efd9beb715927e0db7b138ddbb2925bc2c06fMarc Blank        return apply(context, ops);
2868d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    }
2878d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank
2888d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    // Convenience methods
2891b9efd9beb715927e0db7b138ddbb2925bc2c06fMarc Blank    private static int apply(Context context, ArrayList<ConversationOperation> operations) {
2908d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        ContentProviderClient client =
2918d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank                context.getContentResolver().acquireContentProviderClient(
2928d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank                        ConversationProvider.AUTHORITY);
2938d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        try {
2948d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank            ConversationProvider cp = (ConversationProvider)client.getLocalContentProvider();
2951b9efd9beb715927e0db7b138ddbb2925bc2c06fMarc Blank            return cp.apply(operations);
2968d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        } finally {
2978d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank            client.release();
2988d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        }
2993f1eb8517cf7db29ceafa1912ae999af186e2856Marc Blank    }
3003f1eb8517cf7db29ceafa1912ae999af186e2856Marc Blank
301cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira    public static void undo(final Context context, final Uri undoUri) {
3023f1eb8517cf7db29ceafa1912ae999af186e2856Marc Blank        new Thread(new Runnable() {
3033f1eb8517cf7db29ceafa1912ae999af186e2856Marc Blank            @Override
3043f1eb8517cf7db29ceafa1912ae999af186e2856Marc Blank            public void run() {
305cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira                Cursor c = context.getContentResolver().query(undoUri, UIProvider.UNDO_PROJECTION,
306cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira                        null, null, null);
3073f1eb8517cf7db29ceafa1912ae999af186e2856Marc Blank                if (c != null) {
3083f1eb8517cf7db29ceafa1912ae999af186e2856Marc Blank                    c.close();
3093f1eb8517cf7db29ceafa1912ae999af186e2856Marc Blank                }
310cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira            }
311cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira        }).start();
3123f1eb8517cf7db29ceafa1912ae999af186e2856Marc Blank    }
313f98b318572750dae998a55a60199598933770b68Mindy Pereira
314f98b318572750dae998a55a60199598933770b68Mindy Pereira    public static int archive(Context context, Collection<Conversation> conversations) {
315f98b318572750dae998a55a60199598933770b68Mindy Pereira        ArrayList<ConversationOperation> ops = new ArrayList<ConversationOperation>();
316f98b318572750dae998a55a60199598933770b68Mindy Pereira        for (Conversation conv: conversations) {
317f98b318572750dae998a55a60199598933770b68Mindy Pereira            ConversationOperation op =
318f98b318572750dae998a55a60199598933770b68Mindy Pereira                    new ConversationOperation(ConversationOperation.ARCHIVE, conv);
319f98b318572750dae998a55a60199598933770b68Mindy Pereira            ops.add(op);
320f98b318572750dae998a55a60199598933770b68Mindy Pereira        }
321f98b318572750dae998a55a60199598933770b68Mindy Pereira        return apply(context, ops);
322f98b318572750dae998a55a60199598933770b68Mindy Pereira    }
323830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira
324830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira    public static int mute(Context context, Collection<Conversation> conversations) {
325830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira        ArrayList<ConversationOperation> ops = new ArrayList<ConversationOperation>();
326830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira        for (Conversation conv: conversations) {
327830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira            ConversationOperation op =
328830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira                    new ConversationOperation(ConversationOperation.MUTE, conv);
329830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira            ops.add(op);
330830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira        }
331830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira        return apply(context, ops);
332830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira    }
333830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira
334830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira    public static int reportSpam(Context context, Collection<Conversation> conversations) {
335830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira        ArrayList<ConversationOperation> ops = new ArrayList<ConversationOperation>();
336830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira        for (Conversation conv: conversations) {
337830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira            ConversationOperation op =
338830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira                    new ConversationOperation(ConversationOperation.REPORT_SPAM, conv);
339830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira            ops.add(op);
340830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira        }
341830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira        return apply(context, ops);
342830c00f18b199f4eb2b2cc05b7038b8b05d8eca9Mindy Pereira    }
3431b9efd9beb715927e0db7b138ddbb2925bc2c06fMarc Blank}