Message.java revision 47aa9c991b33c722a6ba1946fc02e0aba17bc1c9
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.provider.BaseColumns;
26import android.text.TextUtils;
27
28import com.android.mail.providers.UIProvider.MessageColumns;
29import com.android.mail.utils.Utils;
30
31import java.util.Collections;
32import java.util.List;
33
34
35public class Message implements Parcelable {
36    /**
37     * @see BaseColumns#_ID
38     */
39    public long id;
40    /**
41     * @see UIProvider.MessageColumns#SERVER_ID
42     */
43    public long serverId;
44    /**
45     * @see UIProvider.MessageColumns#URI
46     */
47    public Uri uri;
48    /**
49     * @see UIProvider.MessageColumns#CONVERSATION_ID
50     */
51    public Uri conversationUri;
52    /**
53     * @see UIProvider.MessageColumns#SUBJECT
54     */
55    public String subject;
56    /**
57     * @see UIProvider.MessageColumns#SNIPPET
58     */
59    public String snippet;
60    /**
61     * @see UIProvider.MessageColumns#FROM
62     */
63    public String from;
64    /**
65     * @see UIProvider.MessageColumns#TO
66     */
67    public String to;
68    /**
69     * @see UIProvider.MessageColumns#CC
70     */
71    public String cc;
72    /**
73     * @see UIProvider.MessageColumns#BCC
74     */
75    public String bcc;
76    /**
77     * @see UIProvider.MessageColumns#REPLY_TO
78     */
79    public String replyTo;
80    /**
81     * @see UIProvider.MessageColumns#DATE_RECEIVED_MS
82     */
83    public long dateReceivedMs;
84    /**
85     * @see UIProvider.MessageColumns#BODY_HTML
86     */
87    public String bodyHtml;
88    /**
89     * @see UIProvider.MessageColumns#BODY_TEXT
90     */
91    public String bodyText;
92    /**
93     * @see UIProvider.MessageColumns#EMBEDS_EXTERNAL_RESOURCES
94     */
95    public boolean embedsExternalResources;
96    /**
97     * @see UIProvider.MessageColumns#REF_MESSAGE_ID
98     */
99    public String refMessageId;
100    /**
101     * @see UIProvider.MessageColumns#DRAFT_TYPE
102     */
103    public int draftType;
104    /**
105     * @see UIProvider.MessageColumns#APPEND_REF_MESSAGE_CONTENT
106     */
107    public boolean appendRefMessageContent;
108    /**
109     * @see UIProvider.MessageColumns#HAS_ATTACHMENTS
110     */
111    public boolean hasAttachments;
112    /**
113     * @see UIProvider.MessageColumns#ATTACHMENT_LIST_URI
114     */
115    public Uri attachmentListUri;
116    /**
117     * @see UIProvider.MessageColumns#MESSAGE_FLAGS
118     */
119    public long messageFlags;
120    /**
121     * @see UIProvider.MessageColumns#SAVE_MESSAGE_URI
122     */
123    public String saveUri;
124    /**
125     * @see UIProvider.MessageColumns#SEND_MESSAGE_URI
126     */
127    public String sendUri;
128    /**
129     * @see UIProvider.MessageColumns#ALWAYS_SHOW_IMAGES
130     */
131    public boolean alwaysShowImages;
132    /**
133     * @see UIProvider.MessageColumns#READ
134     */
135    public boolean read;
136    /**
137     * @see UIProvider.MessageColumns#STARRED
138     */
139    public boolean starred;
140    /**
141     * @see UIProvider.MessageColumns#QUOTE_START_POS
142     */
143    public int quotedTextOffset;
144    /**
145     * @see UIProvider.MessageColumns#ATTACHMENTS
146     */
147    public String attachmentsJson;
148    /**
149     * @see UIProvider.MessageColumns#MESSAGE_ACCOUNT_URI
150     */
151    public Uri accountUri;
152    /**
153     * @see UIProvider.MessageColumns#EVENT_INTENT_URI
154     */
155    public Uri eventIntentUri;
156    /**
157     * @see UIProvider.MessageColumns#SPAM_WARNING_STRING
158     */
159    public String spamWarningString;
160    /**
161     * @see UIProvider.MessageColumns#SPAM_WARNING_LEVEL
162     */
163    public int spamWarningLevel;
164    /**
165     * @see UIProvider.MessageColumns#SPAM_WARNING_LINK_TYPE
166     */
167    public int spamLinkType;
168    /**
169     * @see UIProvider.MessageColumns#VIA_DOMAIN
170     */
171    public String viaDomain;
172    /**
173     * @see UIProvider.MessageColumns#IS_SENDING
174     */
175    public boolean isSending;
176
177    private transient String[] mFromAddresses = null;
178    private transient String[] mToAddresses = null;
179    private transient String[] mCcAddresses = null;
180    private transient String[] mBccAddresses = null;
181    private transient String[] mReplyToAddresses = null;
182
183    private transient List<Attachment> mAttachments = null;
184
185    @Override
186    public int describeContents() {
187        return 0;
188    }
189
190    @Override
191    public boolean equals(Object o) {
192        if (o == null || !(o instanceof Message)) {
193            return false;
194        }
195        final Uri otherUri = ((Message) o).uri;
196        if (uri == null) {
197            return (otherUri == null);
198        }
199        return uri.equals(otherUri);
200    }
201
202    @Override
203    public int hashCode() {
204        return uri == null ? 0 : uri.hashCode();
205    }
206
207    @Override
208    public void writeToParcel(Parcel dest, int flags) {
209        dest.writeLong(id);
210        dest.writeLong(serverId);
211        dest.writeParcelable(uri, 0);
212        dest.writeParcelable(conversationUri, 0);
213        dest.writeString(subject);
214        dest.writeString(snippet);
215        dest.writeString(from);
216        dest.writeString(to);
217        dest.writeString(cc);
218        dest.writeString(bcc);
219        dest.writeString(replyTo);
220        dest.writeLong(dateReceivedMs);
221        dest.writeString(bodyHtml);
222        dest.writeString(bodyText);
223        dest.writeInt(embedsExternalResources ? 1 : 0);
224        dest.writeString(refMessageId);
225        dest.writeInt(draftType);
226        dest.writeInt(appendRefMessageContent ? 1 : 0);
227        dest.writeInt(hasAttachments ? 1 : 0);
228        dest.writeParcelable(attachmentListUri, 0);
229        dest.writeLong(messageFlags);
230        dest.writeString(saveUri);
231        dest.writeString(sendUri);
232        dest.writeInt(alwaysShowImages ? 1 : 0);
233        dest.writeInt(quotedTextOffset);
234        dest.writeString(attachmentsJson);
235        dest.writeParcelable(accountUri, 0);
236        dest.writeParcelable(eventIntentUri, 0);
237        dest.writeString(spamWarningString);
238        dest.writeInt(spamWarningLevel);
239        dest.writeInt(spamLinkType);
240        dest.writeString(viaDomain);
241        dest.writeInt(isSending ? 1 : 0);
242    }
243
244    private Message(Parcel in) {
245        id = in.readLong();
246        serverId = in.readLong();
247        uri = in.readParcelable(null);
248        conversationUri = in.readParcelable(null);
249        subject = in.readString();
250        snippet = in.readString();
251        from = in.readString();
252        to = in.readString();
253        cc = in.readString();
254        bcc = in.readString();
255        replyTo = in.readString();
256        dateReceivedMs = in.readLong();
257        bodyHtml = in.readString();
258        bodyText = in.readString();
259        embedsExternalResources = in.readInt() != 0;
260        refMessageId = in.readString();
261        draftType = in.readInt();
262        appendRefMessageContent = in.readInt() != 0;
263        hasAttachments = in.readInt() != 0;
264        attachmentListUri = in.readParcelable(null);
265        messageFlags = in.readLong();
266        saveUri = in.readString();
267        sendUri = in.readString();
268        alwaysShowImages = in.readInt() != 0;
269        quotedTextOffset = in.readInt();
270        attachmentsJson = in.readString();
271        accountUri = in.readParcelable(null);
272        eventIntentUri = in.readParcelable(null);
273        spamWarningString = in.readString();
274        spamWarningLevel = in.readInt();
275        spamLinkType = in.readInt();
276        viaDomain = in.readString();
277        isSending = in.readInt() != 0;
278    }
279
280    public Message() {
281
282    }
283
284    @Override
285    public String toString() {
286        return "[message id=" + id + "]";
287    }
288
289    public static final Creator<Message> CREATOR = new Creator<Message>() {
290
291        @Override
292        public Message createFromParcel(Parcel source) {
293            return new Message(source);
294        }
295
296        @Override
297        public Message[] newArray(int size) {
298            return new Message[size];
299        }
300
301    };
302
303    public Message(Cursor cursor) {
304        if (cursor != null) {
305            id = cursor.getLong(UIProvider.MESSAGE_ID_COLUMN);
306            serverId = cursor.getLong(UIProvider.MESSAGE_SERVER_ID_COLUMN);
307            final String messageUriStr = cursor.getString(UIProvider.MESSAGE_URI_COLUMN);
308            uri = !TextUtils.isEmpty(messageUriStr) ? Uri.parse(messageUriStr) : null;
309            final String convUriStr = cursor.getString(UIProvider.MESSAGE_CONVERSATION_URI_COLUMN);
310            conversationUri = !TextUtils.isEmpty(convUriStr) ? Uri.parse(convUriStr) : null;
311            subject = cursor.getString(UIProvider.MESSAGE_SUBJECT_COLUMN);
312            snippet = cursor.getString(UIProvider.MESSAGE_SNIPPET_COLUMN);
313            from = cursor.getString(UIProvider.MESSAGE_FROM_COLUMN);
314            to = cursor.getString(UIProvider.MESSAGE_TO_COLUMN);
315            cc = cursor.getString(UIProvider.MESSAGE_CC_COLUMN);
316            bcc = cursor.getString(UIProvider.MESSAGE_BCC_COLUMN);
317            replyTo = cursor.getString(UIProvider.MESSAGE_REPLY_TO_COLUMN);
318            dateReceivedMs = cursor.getLong(UIProvider.MESSAGE_DATE_RECEIVED_MS_COLUMN);
319            bodyHtml = cursor.getString(UIProvider.MESSAGE_BODY_HTML_COLUMN);
320            bodyText = cursor.getString(UIProvider.MESSAGE_BODY_TEXT_COLUMN);
321            embedsExternalResources = cursor
322                    .getInt(UIProvider.MESSAGE_EMBEDS_EXTERNAL_RESOURCES_COLUMN) != 0;
323            refMessageId = cursor.getString(UIProvider.MESSAGE_REF_MESSAGE_ID_COLUMN);
324            draftType = cursor.getInt(UIProvider.MESSAGE_DRAFT_TYPE_COLUMN);
325            appendRefMessageContent = cursor
326                    .getInt(UIProvider.MESSAGE_APPEND_REF_MESSAGE_CONTENT_COLUMN) != 0;
327            hasAttachments = cursor.getInt(UIProvider.MESSAGE_HAS_ATTACHMENTS_COLUMN) != 0;
328            final String attachmentsUri = cursor
329                    .getString(UIProvider.MESSAGE_ATTACHMENT_LIST_URI_COLUMN);
330            attachmentListUri = hasAttachments && !TextUtils.isEmpty(attachmentsUri) ? Uri
331                    .parse(attachmentsUri) : null;
332            messageFlags = cursor.getLong(UIProvider.MESSAGE_FLAGS_COLUMN);
333            saveUri = cursor
334                    .getString(UIProvider.MESSAGE_SAVE_URI_COLUMN);
335            sendUri = cursor
336                    .getString(UIProvider.MESSAGE_SEND_URI_COLUMN);
337            alwaysShowImages = cursor.getInt(UIProvider.MESSAGE_ALWAYS_SHOW_IMAGES_COLUMN) != 0;
338            read = cursor.getInt(UIProvider.MESSAGE_READ_COLUMN) != 0;
339            starred = cursor.getInt(UIProvider.MESSAGE_STARRED_COLUMN) != 0;
340            quotedTextOffset = cursor.getInt(UIProvider.QUOTED_TEXT_OFFSET_COLUMN);
341            attachmentsJson = cursor.getString(UIProvider.MESSAGE_ATTACHMENTS_COLUMN);
342            String accountUriString = cursor.getString(UIProvider.MESSAGE_ACCOUNT_URI_COLUMN);
343            accountUri = !TextUtils.isEmpty(accountUriString) ? Uri.parse(accountUriString) : null;
344            eventIntentUri =
345                    Utils.getValidUri(cursor.getString(UIProvider.MESSAGE_EVENT_INTENT_COLUMN));
346            spamWarningString =
347                    cursor.getString(UIProvider.MESSAGE_SPAM_WARNING_STRING_ID_COLUMN);
348            spamWarningLevel = cursor.getInt(UIProvider.MESSAGE_SPAM_WARNING_LEVEL_COLUMN);
349            spamLinkType = cursor.getInt(UIProvider.MESSAGE_SPAM_WARNING_LINK_TYPE_COLUMN);
350            viaDomain = cursor.getString(UIProvider.MESSAGE_VIA_DOMAIN_COLUMN);
351            isSending = cursor.getInt(UIProvider.MESSAGE_IS_SENDING_COLUMN) != 0;
352        }
353    }
354
355    public boolean isFlaggedReplied() {
356        return (messageFlags & UIProvider.MessageFlags.REPLIED) ==
357                UIProvider.MessageFlags.REPLIED;
358    }
359
360    public boolean isFlaggedForwarded() {
361        return (messageFlags & UIProvider.MessageFlags.FORWARDED) ==
362                UIProvider.MessageFlags.FORWARDED;
363    }
364
365    public boolean isFlaggedCalendarInvite() {
366        return (messageFlags & UIProvider.MessageFlags.CALENDAR_INVITE) ==
367                UIProvider.MessageFlags.CALENDAR_INVITE;
368    }
369
370    public synchronized String[] getFromAddresses() {
371        if (mFromAddresses == null) {
372            mFromAddresses = Utils.splitCommaSeparatedString(from);
373        }
374        return mFromAddresses;
375    }
376
377    public synchronized String[] getToAddresses() {
378        if (mToAddresses == null) {
379            mToAddresses = Utils.splitCommaSeparatedString(to);
380        }
381        return mToAddresses;
382    }
383
384    public synchronized String[] getCcAddresses() {
385        if (mCcAddresses == null) {
386            mCcAddresses = Utils.splitCommaSeparatedString(cc);
387        }
388        return mCcAddresses;
389    }
390
391    public synchronized String[] getBccAddresses() {
392        if (mBccAddresses == null) {
393            mBccAddresses = Utils.splitCommaSeparatedString(bcc);
394        }
395        return mBccAddresses;
396    }
397
398    public synchronized String[] getReplyToAddresses() {
399        if (mReplyToAddresses == null) {
400            mReplyToAddresses = Utils.splitCommaSeparatedString(replyTo);
401        }
402        return mReplyToAddresses;
403    }
404
405    public synchronized List<Attachment> getAttachments() {
406        if (mAttachments == null) {
407            if (attachmentsJson != null) {
408                mAttachments = Attachment.fromJSONArray(attachmentsJson);
409            } else {
410                mAttachments = Collections.emptyList();
411            }
412        }
413        return mAttachments;
414    }
415
416    /**
417     * Returns whether a "Show Pictures" button should initially appear for this message. If the
418     * button is shown, the message must also block all non-local images in the body. Inversely, if
419     * the button is not shown, the message must show all images within (or else the user would be
420     * stuck with no images and no way to reveal them).
421     *
422     * @return true if a "Show Pictures" button should appear.
423     */
424    public boolean shouldShowImagePrompt() {
425        return embedsExternalResources && !alwaysShowImages;
426    }
427
428    /**
429     * Helper method to command a provider to mark all messages from this sender with the
430     * {@link MessageColumns#ALWAYS_SHOW_IMAGES} flag set.
431     *
432     * @param handler a caller-provided handler to run the query on
433     * @param token (optional) token to identify the command to the handler
434     * @param cookie (optional) cookie to pass to the handler
435     */
436    public void markAlwaysShowImages(AsyncQueryHandler handler, int token, Object cookie) {
437        alwaysShowImages = true;
438
439        final ContentValues values = new ContentValues(1);
440        values.put(UIProvider.MessageColumns.ALWAYS_SHOW_IMAGES, 1);
441
442        handler.startUpdate(token, cookie, uri, values, null, null);
443    }
444
445}
446