Conversation.java revision f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91
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;
26732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
278d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blankimport com.android.mail.browse.ConversationCursor.ConversationOperation;
288d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blankimport com.android.mail.browse.ConversationCursor.ConversationProvider;
298d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank
308d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blankimport java.util.ArrayList;
318d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blankimport java.util.Collection;
328d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank
33732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangpublic class Conversation implements Parcelable {
34f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank    public static final int NO_POSITION = -1;
35732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
36732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public long id;
37732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public String subject;
38732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public long dateMs;
39732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public String snippet;
40732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public boolean hasAttachments;
41732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public Uri messageListUri;
424db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public String senders;
434db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int numMessages;
444db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int numDrafts;
454db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int sendingState;
464db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira    public int priority;
47c8a994227b9c686d88ee05840544162711a85712Marc Blank    public boolean read;
48c8a994227b9c686d88ee05840544162711a85712Marc Blank    public boolean starred;
49f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank    public transient int position;
50732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
51732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
52732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public int describeContents() {
53732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        return 0;
54732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
55732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
56732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
57732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public void writeToParcel(Parcel dest, int flags) {
58732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeLong(id);
59732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeString(subject);
60732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeLong(dateMs);
61732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeString(snippet);
62732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeByte(hasAttachments ? (byte) 1 : 0);
63732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dest.writeParcelable(messageListUri, flags);
644db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeString(senders);
654db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(numMessages);
664db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(numDrafts);
674db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(sendingState);
684db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        dest.writeInt(priority);
69c8a994227b9c686d88ee05840544162711a85712Marc Blank        dest.writeByte(read ? (byte) 1 : 0);
70c8a994227b9c686d88ee05840544162711a85712Marc Blank        dest.writeByte(starred ? (byte) 1 : 0);
71732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
72732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
73732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    private Conversation(Parcel in) {
74732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        id = in.readLong();
75732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        subject = in.readString();
76732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        dateMs = in.readLong();
77732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        snippet = in.readString();
78732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        hasAttachments = (in.readByte() != 0);
79732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        messageListUri = in.readParcelable(null);
804db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        senders = in.readString();
814db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        numMessages = in.readInt();
824db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        numDrafts = in.readInt();
834db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        sendingState = in.readInt();
844db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira        priority = in.readInt();
85c8a994227b9c686d88ee05840544162711a85712Marc Blank        read = (in.readByte() != 0);
86c8a994227b9c686d88ee05840544162711a85712Marc Blank        starred = (in.readByte() != 0);
87f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank        position = NO_POSITION;
88732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
89732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
90732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    @Override
91732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public String toString() {
92732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        return "[conversation id=" + id + "]";
93732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
94732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
95732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public static final Creator<Conversation> CREATOR = new Creator<Conversation>() {
96732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
97732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        @Override
98732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        public Conversation createFromParcel(Parcel source) {
99732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            return new Conversation(source);
100732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
101732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
102732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        @Override
103732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        public Conversation[] newArray(int size) {
104732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            return new Conversation[size];
105732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
106732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
107732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    };
108732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
109732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public static Conversation from(Cursor cursor) {
110732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        return new Conversation(cursor);
111732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
112732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
113732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    private Conversation(Cursor cursor) {
114732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        if (cursor != null) {
115732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            id = cursor.getLong(UIProvider.CONVERSATION_ID_COLUMN);
116732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            dateMs = cursor.getLong(UIProvider.CONVERSATION_DATE_RECEIVED_MS_COLUMN);
117732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            subject = cursor.getString(UIProvider.CONVERSATION_SUBJECT_COLUMN);
118374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank            // Don't allow null subject
119374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank            if (subject == null) {
120374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank                subject = "";
121374863eeb0ee37f1ca7d57840e6f02aaa052e284Marc Blank            }
122732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            snippet = cursor.getString(UIProvider.CONVERSATION_SNIPPET_COLUMN);
123c8a994227b9c686d88ee05840544162711a85712Marc Blank            hasAttachments = cursor.getInt(UIProvider.CONVERSATION_HAS_ATTACHMENTS_COLUMN) == 1;
124732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            messageListUri = Uri.parse(cursor
125732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang                    .getString(UIProvider.CONVERSATION_MESSAGE_LIST_URI_COLUMN));
1264db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            senders = cursor.getString(UIProvider.CONVERSATION_SENDER_INFO_COLUMN);
1274db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            numMessages = cursor.getInt(UIProvider.CONVERSATION_NUM_MESSAGES_COLUMN);
1284db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            numDrafts = cursor.getInt(UIProvider.CONVERSATION_NUM_DRAFTS_COLUMN);
1294db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            sendingState = cursor.getInt(UIProvider.CONVERSATION_SENDING_STATE_COLUMN);
1304db59c58c0af9f44d95a12dbe21322bed58cc518Mindy Pereira            priority = cursor.getInt(UIProvider.CONVERSATION_PRIORITY_COLUMN);
131c8a994227b9c686d88ee05840544162711a85712Marc Blank            read = cursor.getInt(UIProvider.CONVERSATION_READ_COLUMN) == 1;
132c8a994227b9c686d88ee05840544162711a85712Marc Blank            starred = cursor.getInt(UIProvider.CONVERSATION_STARRED_COLUMN) == 1;
133f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank            position = NO_POSITION;
134732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        }
135732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
136732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
137c8a994227b9c686d88ee05840544162711a85712Marc Blank    // Below are methods that update Conversation data (update/delete)
138c8a994227b9c686d88ee05840544162711a85712Marc Blank
1398d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    /**
1408d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * Update a boolean column for a single conversation
1418d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param context the caller's context
1428d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param columnName the column to update
1438d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param value the new value
1448d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     */
145c8a994227b9c686d88ee05840544162711a85712Marc Blank    public void updateBoolean(Context context, String columnName, boolean value) {
146c8a994227b9c686d88ee05840544162711a85712Marc Blank        ContentValues cv = new ContentValues();
147c8a994227b9c686d88ee05840544162711a85712Marc Blank        cv.put(columnName, value);
148c8a994227b9c686d88ee05840544162711a85712Marc Blank        context.getContentResolver().update(messageListUri, cv, null, null);
149c8a994227b9c686d88ee05840544162711a85712Marc Blank    }
150c8a994227b9c686d88ee05840544162711a85712Marc Blank
1518d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    /**
1528d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * Update a boolean column for a group of conversations, immediately in the UI and in a single
1538d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * transaction in the underlying provider
1548d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param conversations a collection of conversations
1558d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param context the caller's context
1568d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param columnName the column to update
1578d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param value the new value
1588d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     */
1598d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    public static void updateBoolean(Context context, Collection<Conversation> conversations,
1608d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank            String columnName, boolean value) {
1618d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        ContentValues cv = new ContentValues();
1628d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        cv.put(columnName, value);
1638d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        ArrayList<ConversationOperation> ops = new ArrayList<ConversationOperation>();
1648d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        for (Conversation conv: conversations) {
1658d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank            ConversationOperation op =
166f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank                    new ConversationOperation(ConversationOperation.UPDATE, conv, cv);
1678d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank            ops.add(op);
1688d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        }
1698d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        apply(context, ops);
1708d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    }
1718d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank
1728d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    /**
1738d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * Delete a single conversation
1748d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param context the caller's context
1758d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     */
176c8a994227b9c686d88ee05840544162711a85712Marc Blank    public void delete(Context context) {
177c8a994227b9c686d88ee05840544162711a85712Marc Blank        context.getContentResolver().delete(messageListUri, null, null);
178c8a994227b9c686d88ee05840544162711a85712Marc Blank    }
1798d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank
1808d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    /**
1818d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * Delete a group of conversations immediately in the UI and in a single transaction in the
1828d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * underlying provider
1838d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param context the caller's context
1848d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     * @param conversations a collection of conversations
1858d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank     */
1868d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    public static void delete(Context context, Collection<Conversation> conversations) {
1878d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        ArrayList<ConversationOperation> ops = new ArrayList<ConversationOperation>();
1888d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        for (Conversation conv: conversations) {
1898d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank            ConversationOperation op =
190f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blank                    new ConversationOperation(ConversationOperation.DELETE, conv);
1918d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank            ops.add(op);
1928d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        }
1938d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        apply(context, ops);
1948d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    }
1958d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank
1968d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    // Convenience methods
1978d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    private static void apply(Context context, ArrayList<ConversationOperation> operations) {
1988d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        ContentProviderClient client =
1998d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank                context.getContentResolver().acquireContentProviderClient(
2008d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank                        ConversationProvider.AUTHORITY);
2018d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        try {
2028d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank            ConversationProvider cp = (ConversationProvider)client.getLocalContentProvider();
2038d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank            cp.apply(operations);
2048d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        } finally {
2058d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank            client.release();
2068d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        }
2078d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank    }
208732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang}
209