18812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein/*
28812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * Copyright (C) 2013 Google Inc.
38812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * Licensed to The Android Open Source Project.
48812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein *
58812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * Licensed under the Apache License, Version 2.0 (the "License");
68812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * you may not use this file except in compliance with the License.
78812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * You may obtain a copy of the License at
88812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein *
98812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein *      http://www.apache.org/licenses/LICENSE-2.0
108812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein *
118812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * Unless required by applicable law or agreed to in writing, software
128812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * distributed under the License is distributed on an "AS IS" BASIS,
138812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
148812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * See the License for the specific language governing permissions and
158812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * limitations under the License.
168812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein */
178812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
188812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinpackage com.android.mail.browse;
198812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
207434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport android.content.Context;
218812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport android.database.Cursor;
228812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport android.net.Uri;
238812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
248812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.android.emailcommon.internet.MimeMessage;
258812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.android.emailcommon.mail.MessagingException;
268812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.android.mail.browse.MessageCursor.ConversationController;
278812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.android.mail.content.CursorCreator;
284f347e811052f446c3958c76db278bcd7b39a44fAndy Huangimport com.android.mail.providers.Account;
298812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.android.mail.providers.Attachment;
308812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.android.mail.providers.Conversation;
318812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.android.mail.providers.Message;
328812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.android.mail.ui.ConversationUpdater;
338812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.google.common.base.Objects;
348812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
358812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein/**
368812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * A message created as part of a conversation view. Sometimes, like during star/unstar, it's
378812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * handy to have the owning {@link com.android.mail.providers.Conversation} for context.
388812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein *
398812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * <p>This class must remain separate from the {@link MessageCursor} from whence it came,
408812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * because cursors can be closed by their Loaders at any time. The
418812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * {@link ConversationController} intermediate is used to obtain the currently opened cursor.
428812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein *
438812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * <p>(N.B. This is a {@link android.os.Parcelable}, so try not to add non-transient fields here.
448812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * Parcelable state belongs either in {@link com.android.mail.providers.Message} or
458812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * {@link com.android.mail.ui.ConversationViewState.MessageViewState}. The
468812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein * assumption is that this class never needs the state of its extra context saved.)
478812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein */
488812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinpublic final class ConversationMessage extends Message {
498812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
508812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    private transient ConversationController mController;
518812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
528812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    private ConversationMessage(Cursor cursor) {
538812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        super(cursor);
548812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    }
558812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
567434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein    public ConversationMessage(Context context, MimeMessage mimeMessage, Uri emlFileUri)
577434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein            throws MessagingException {
587434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein        super(context, mimeMessage, emlFileUri);
598812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    }
608812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
618812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    public void setController(ConversationController controller) {
628812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        mController = controller;
638812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    }
648812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
658812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    public Conversation getConversation() {
664ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein        return mController != null ? mController.getConversation() : null;
678812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    }
688812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
694f347e811052f446c3958c76db278bcd7b39a44fAndy Huang    public Account getAccount() {
704f347e811052f446c3958c76db278bcd7b39a44fAndy Huang        return mController != null ? mController.getAccount() : null;
714f347e811052f446c3958c76db278bcd7b39a44fAndy Huang    }
724f347e811052f446c3958c76db278bcd7b39a44fAndy Huang
738812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    /**
748812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein     * Returns a hash code based on this message's identity, contents and current state.
758812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein     * This is a separate method from hashCode() to allow for an instance of this class to be
768812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein     * a functional key in a hash-based data structure.
778812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein     *
788812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein     */
798812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    public int getStateHashCode() {
808812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        return Objects.hashCode(uri, read, starred, getAttachmentsStateHashCode());
818812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    }
828812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
838812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    private int getAttachmentsStateHashCode() {
848812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        int hash = 0;
858812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        for (Attachment a : getAttachments()) {
868812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein            final Uri uri = a.getIdentifierUri();
878812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein            hash += (uri != null ? uri.hashCode() : 0);
888812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        }
898812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        return hash;
908812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    }
918812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
928812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    public boolean isConversationStarred() {
938812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        final MessageCursor c = mController.getMessageCursor();
948812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        return c != null && c.isConversationStarred();
958812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    }
968812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
978812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    public void star(boolean newStarred) {
988812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        final ConversationUpdater listController = mController.getListController();
998812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        if (listController != null) {
1008812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein            listController.starMessage(this, newStarred);
1018812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        }
1028812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    }
1038812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
1048812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    /**
1058812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein     * Public object that knows how to construct Messages given Cursors.
1068812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein     */
1078812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    public static final CursorCreator<ConversationMessage> FACTORY =
1088812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein            new CursorCreator<ConversationMessage>() {
1098812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein                @Override
1108812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein                public ConversationMessage createFromCursor(Cursor c) {
1118812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein                    return new ConversationMessage(c);
1128812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein                }
1138812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
1148812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein                @Override
1158812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein                public String toString() {
1168812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein                    return "ConversationMessage CursorCreator";
1178812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein                }
1188812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein            };
1198812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
1208812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein}
121