Message.java revision bec5115726f24733a0a1577caaf05fb6e9ef9c6f
1/**
2 * Copyright (c) 2012, Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.mail.providers;
18
19import android.content.AsyncQueryHandler;
20import android.content.ContentValues;
21import android.database.Cursor;
22import android.net.Uri;
23import android.os.Parcel;
24import android.os.Parcelable;
25import android.text.TextUtils;
26
27import com.android.mail.browse.ConversationCursor;
28import com.android.mail.providers.UIProvider.ConversationColumns;
29import com.android.mail.providers.UIProvider.MessageColumns;
30import com.android.mail.ui.ConversationViewFragment.MessageCursor;
31import com.android.mail.utils.Utils;
32
33
34public class Message implements Parcelable {
35    public long id;
36    public long serverId;
37    public Uri uri;
38    public String conversationUri;
39    public String subject;
40    public String snippet;
41    public String from;
42    public String to;
43    public String cc;
44    public String bcc;
45    public String replyTo;
46    public long dateReceivedMs;
47    public String bodyHtml;
48    public String bodyText;
49    public boolean embedsExternalResources;
50    public String refMessageId;
51    public int draftType;
52    public boolean appendRefMessageContent;
53    public boolean hasAttachments;
54    public Uri attachmentListUri;
55    public long messageFlags;
56    public String joinedAttachmentInfos;
57    public String saveUri;
58    public String sendUri;
59    public boolean alwaysShowImages;
60    public boolean read;
61    public boolean starred;
62    public int quotedTextOffset;
63
64    private String[] mToAddresses = null;
65    private String[] mCcAddresses = null;
66    private String[] mBccAddresses = null;
67    private String[] mReplyToAddresses = null;
68
69    // While viewing a list of messages, points to the MessageCursor that contains it
70    private transient MessageCursor mMessageCursor = null;
71
72    @Override
73    public int describeContents() {
74        return 0;
75    }
76
77    @Override
78    public boolean equals(Object o) {
79        if (o == null || !(o instanceof Message)) {
80            return false;
81        }
82        final Uri otherUri = ((Message) o).uri;
83        if (uri == null) {
84            return (otherUri == null);
85        }
86        return uri.equals(otherUri);
87    }
88
89    @Override
90    public int hashCode() {
91        return uri == null ? 0 : uri.hashCode();
92    }
93
94    @Override
95    public void writeToParcel(Parcel dest, int flags) {
96        dest.writeLong(id);
97        dest.writeLong(serverId);
98        dest.writeParcelable(uri, 0);
99        dest.writeString(conversationUri);
100        dest.writeString(subject);
101        dest.writeString(snippet);
102        dest.writeString(from);
103        dest.writeString(to);
104        dest.writeString(cc);
105        dest.writeString(bcc);
106        dest.writeString(replyTo);
107        dest.writeLong(dateReceivedMs);
108        dest.writeString(bodyHtml);
109        dest.writeString(bodyText);
110        dest.writeInt(embedsExternalResources ? 1 : 0);
111        dest.writeString(refMessageId);
112        dest.writeInt(draftType);
113        dest.writeInt(appendRefMessageContent ? 1 : 0);
114        dest.writeInt(hasAttachments ? 1 : 0);
115        dest.writeParcelable(attachmentListUri, 0);
116        dest.writeLong(messageFlags);
117        dest.writeString(joinedAttachmentInfos);
118        dest.writeString(saveUri);
119        dest.writeString(sendUri);
120        dest.writeInt(alwaysShowImages ? 1 : 0);
121        dest.writeInt(quotedTextOffset);
122    }
123
124    private Message(Parcel in) {
125        id = in.readLong();
126        serverId = in.readLong();
127        uri = in.readParcelable(null);
128        conversationUri = in.readString();
129        subject = in.readString();
130        snippet = in.readString();
131        from = in.readString();
132        to = in.readString();
133        cc = in.readString();
134        bcc = in.readString();
135        replyTo = in.readString();
136        dateReceivedMs = in.readLong();
137        bodyHtml = in.readString();
138        bodyText = in.readString();
139        embedsExternalResources = in.readInt() != 0;
140        refMessageId = in.readString();
141        draftType = in.readInt();
142        appendRefMessageContent = in.readInt() != 0;
143        hasAttachments = in.readInt() != 0;
144        attachmentListUri = in.readParcelable(null);
145        messageFlags = in.readLong();
146        joinedAttachmentInfos = in.readString();
147        saveUri = in.readString();
148        sendUri = in.readString();
149        alwaysShowImages = in.readInt() != 0;
150        quotedTextOffset = in.readInt();
151    }
152
153    public Message() {
154
155    }
156
157    @Override
158    public String toString() {
159        return "[message id=" + id + "]";
160    }
161
162    public static final Creator<Message> CREATOR = new Creator<Message>() {
163
164        @Override
165        public Message createFromParcel(Parcel source) {
166            return new Message(source);
167        }
168
169        @Override
170        public Message[] newArray(int size) {
171            return new Message[size];
172        }
173
174    };
175
176    public Message(MessageCursor cursor) {
177        this((Cursor)cursor);
178        // Only set message cursor if appropriate
179        mMessageCursor = cursor;
180    }
181
182    public Message(Cursor cursor) {
183        if (cursor != null) {
184            id = cursor.getLong(UIProvider.MESSAGE_ID_COLUMN);
185            serverId = cursor.getLong(UIProvider.MESSAGE_SERVER_ID_COLUMN);
186            String message = cursor.getString(UIProvider.MESSAGE_URI_COLUMN);
187            uri = !TextUtils.isEmpty(message) ? Uri.parse(message) : null;
188            conversationUri = cursor.getString(UIProvider.MESSAGE_CONVERSATION_URI_COLUMN);
189            subject = cursor.getString(UIProvider.MESSAGE_SUBJECT_COLUMN);
190            snippet = cursor.getString(UIProvider.MESSAGE_SNIPPET_COLUMN);
191            from = cursor.getString(UIProvider.MESSAGE_FROM_COLUMN);
192            to = cursor.getString(UIProvider.MESSAGE_TO_COLUMN);
193            cc = cursor.getString(UIProvider.MESSAGE_CC_COLUMN);
194            bcc = cursor.getString(UIProvider.MESSAGE_BCC_COLUMN);
195            replyTo = cursor.getString(UIProvider.MESSAGE_REPLY_TO_COLUMN);
196            dateReceivedMs = cursor.getLong(UIProvider.MESSAGE_DATE_RECEIVED_MS_COLUMN);
197            bodyHtml = cursor.getString(UIProvider.MESSAGE_BODY_HTML_COLUMN);
198            bodyText = cursor.getString(UIProvider.MESSAGE_BODY_TEXT_COLUMN);
199            embedsExternalResources = cursor
200                    .getInt(UIProvider.MESSAGE_EMBEDS_EXTERNAL_RESOURCES_COLUMN) != 0;
201            refMessageId = cursor.getString(UIProvider.MESSAGE_REF_MESSAGE_ID_COLUMN);
202            draftType = cursor.getInt(UIProvider.MESSAGE_DRAFT_TYPE_COLUMN);
203            appendRefMessageContent = cursor
204                    .getInt(UIProvider.MESSAGE_APPEND_REF_MESSAGE_CONTENT_COLUMN) != 0;
205            hasAttachments = cursor.getInt(UIProvider.MESSAGE_HAS_ATTACHMENTS_COLUMN) != 0;
206            final String attachmentsUri = cursor
207                    .getString(UIProvider.MESSAGE_ATTACHMENT_LIST_URI_COLUMN);
208            attachmentListUri = hasAttachments && !TextUtils.isEmpty(attachmentsUri) ? Uri
209                    .parse(attachmentsUri) : null;
210            messageFlags = cursor.getLong(UIProvider.MESSAGE_FLAGS_COLUMN);
211            joinedAttachmentInfos = cursor
212                    .getString(UIProvider.MESSAGE_JOINED_ATTACHMENT_INFOS_COLUMN);
213            saveUri = cursor
214                    .getString(UIProvider.MESSAGE_SAVE_URI_COLUMN);
215            sendUri = cursor
216                    .getString(UIProvider.MESSAGE_SEND_URI_COLUMN);
217            alwaysShowImages = cursor.getInt(UIProvider.MESSAGE_ALWAYS_SHOW_IMAGES_COLUMN) != 0;
218            read = cursor.getInt(UIProvider.MESSAGE_READ_COLUMN) != 0;
219            starred = cursor.getInt(UIProvider.MESSAGE_STARRED_COLUMN) != 0;
220            quotedTextOffset = cursor.getInt(UIProvider.QUOTED_TEXT_OFFSET_COLUMN);
221        }
222    }
223
224    public synchronized String[] getToAddresses() {
225        if (mToAddresses == null) {
226            mToAddresses = Utils.splitCommaSeparatedString(to);
227        }
228        return mToAddresses;
229    }
230
231    public synchronized String[] getCcAddresses() {
232        if (mCcAddresses == null) {
233            mCcAddresses = Utils.splitCommaSeparatedString(cc);
234        }
235        return mCcAddresses;
236    }
237
238    public synchronized String[] getBccAddresses() {
239        if (mBccAddresses == null) {
240            mBccAddresses = Utils.splitCommaSeparatedString(bcc);
241        }
242        return mBccAddresses;
243    }
244
245    public synchronized String[] getReplyToAddresses() {
246        if (mReplyToAddresses == null) {
247            mReplyToAddresses = Utils.splitCommaSeparatedString(replyTo);
248        }
249        return mReplyToAddresses;
250    }
251
252    /**
253     * Returns whether a "Show Pictures" button should initially appear for this message. If the
254     * button is shown, the message must also block all non-local images in the body. Inversely, if
255     * the button is not shown, the message must show all images within (or else the user would be
256     * stuck with no images and no way to reveal them).
257     *
258     * @return true if a "Show Pictures" button should appear.
259     */
260    public boolean shouldShowImagePrompt() {
261        return embedsExternalResources && !alwaysShowImages;
262    }
263
264    /**
265     * Helper method to command a provider to mark all messages from this sender with the
266     * {@link MessageColumns#ALWAYS_SHOW_IMAGES} flag set.
267     *
268     * @param handler a caller-provided handler to run the query on
269     * @param token (optional) token to identify the command to the handler
270     * @param cookie (optional) cookie to pass to the handler
271     */
272    public void markAlwaysShowImages(AsyncQueryHandler handler, int token, Object cookie) {
273        final ContentValues values = new ContentValues(1);
274        values.put(UIProvider.MessageColumns.ALWAYS_SHOW_IMAGES, 1);
275
276        handler.startUpdate(token, cookie, uri, values, null, null);
277    }
278
279    /**
280     * Helper method to command a provider to star/unstar this message.
281     *
282     * @param starred whether to star or unstar the message
283     * @param handler a caller-provided handler to run the query on
284     * @param token (optional) token to identify the command to the handler
285     * @param cookie (optional) cookie to pass to the handler
286     */
287    public void star(boolean starred, AsyncQueryHandler handler, int token, Object cookie) {
288        this.starred = starred;
289        boolean conversationStarred = starred;
290        // If we're unstarring, we need to find out if the conversation is still starred
291        if (mMessageCursor != null && !starred) {
292            conversationStarred = mMessageCursor.isConversationStarred();
293        }
294        // Update the conversation cursor so that changes are reflected simultaneously
295        ConversationCursor.setConversationColumn(conversationUri, ConversationColumns.STARRED,
296                conversationStarred);
297        final ContentValues values = new ContentValues(1);
298        values.put(UIProvider.MessageColumns.STARRED, starred ? 1 : 0);
299
300        handler.startUpdate(token, cookie, uri, values, null, null);
301    }
302
303}
304