1/*
2 * Copyright (C) 2015 The Android Open Source Project
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.messaging.datamodel.action;
18
19import android.os.Parcel;
20import android.os.Parcelable;
21
22import com.android.messaging.datamodel.BugleDatabaseOperations;
23import com.android.messaging.datamodel.DataModel;
24import com.android.messaging.datamodel.DatabaseWrapper;
25import com.android.messaging.datamodel.action.ActionMonitor.ActionCompletedListener;
26import com.android.messaging.datamodel.data.ConversationListItemData;
27import com.android.messaging.datamodel.data.MessageData;
28import com.android.messaging.util.Assert;
29import com.android.messaging.util.Assert.RunsOnMainThread;
30import com.android.messaging.util.LogUtil;
31import com.google.common.annotations.VisibleForTesting;
32
33public class ReadDraftDataAction extends Action implements Parcelable {
34
35    /**
36     * Interface for ReadDraftDataAction listeners
37     */
38    public interface ReadDraftDataActionListener {
39        @RunsOnMainThread
40        abstract void onReadDraftDataSucceeded(final ReadDraftDataAction action,
41                final Object data, final MessageData message,
42                final ConversationListItemData conversation);
43        @RunsOnMainThread
44        abstract void onReadDraftDataFailed(final ReadDraftDataAction action, final Object data);
45    }
46
47    /**
48     * Read draft message and associated data (with listener)
49     */
50    public static ReadDraftDataActionMonitor readDraftData(final String conversationId,
51            final MessageData incomingDraft, final Object data,
52            final ReadDraftDataActionListener listener) {
53        final ReadDraftDataActionMonitor monitor = new ReadDraftDataActionMonitor(data,
54                listener);
55        final ReadDraftDataAction action = new ReadDraftDataAction(conversationId,
56                incomingDraft, monitor.getActionKey());
57        action.start(monitor);
58        return monitor;
59    }
60
61    private static final String KEY_CONVERSATION_ID = "conversationId";
62    private static final String KEY_INCOMING_DRAFT = "draftMessage";
63
64    private ReadDraftDataAction(final String conversationId, final MessageData incomingDraft,
65            final String actionKey) {
66        super(actionKey);
67        actionParameters.putString(KEY_CONVERSATION_ID, conversationId);
68        actionParameters.putParcelable(KEY_INCOMING_DRAFT, incomingDraft);
69    }
70
71    @VisibleForTesting
72    class DraftData {
73        public final MessageData message;
74        public final ConversationListItemData conversation;
75
76        DraftData(final MessageData message, final ConversationListItemData conversation) {
77            this.message = message;
78            this.conversation = conversation;
79        }
80    }
81
82    @Override
83    protected Object executeAction() {
84        final DatabaseWrapper db = DataModel.get().getDatabase();
85        final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
86        final MessageData incomingDraft = actionParameters.getParcelable(KEY_INCOMING_DRAFT);
87        final ConversationListItemData conversation =
88                ConversationListItemData.getExistingConversation(db, conversationId);
89        MessageData message = null;
90        if (conversation != null) {
91            if (incomingDraft == null) {
92                message = BugleDatabaseOperations.readDraftMessageData(db, conversationId,
93                        conversation.getSelfId());
94            }
95            if (message == null) {
96                message = MessageData.createDraftMessage(conversationId, conversation.getSelfId(),
97                        incomingDraft);
98                LogUtil.d(LogUtil.BUGLE_TAG, "ReadDraftMessage: created draft. "
99                        + "conversationId=" + conversationId
100                        + " selfId=" + conversation.getSelfId());
101            } else {
102                LogUtil.d(LogUtil.BUGLE_TAG, "ReadDraftMessage: read draft. "
103                        + "conversationId=" + conversationId
104                        + " selfId=" + conversation.getSelfId());
105            }
106            return new DraftData(message, conversation);
107        }
108        return null;
109    }
110
111    /**
112     * An operation that notifies a listener upon completion
113     */
114    public static class ReadDraftDataActionMonitor extends ActionMonitor
115            implements ActionCompletedListener {
116
117        private final ReadDraftDataActionListener mListener;
118
119        ReadDraftDataActionMonitor(final Object data,
120                final ReadDraftDataActionListener completed) {
121            super(STATE_CREATED, generateUniqueActionKey("ReadDraftDataAction"), data);
122            setCompletedListener(this);
123            mListener = completed;
124        }
125
126        @Override
127        public void onActionSucceeded(final ActionMonitor monitor,
128                final Action action, final Object data, final Object result) {
129            final DraftData draft = (DraftData) result;
130            if (draft == null) {
131                mListener.onReadDraftDataFailed((ReadDraftDataAction) action, data);
132            } else {
133                mListener.onReadDraftDataSucceeded((ReadDraftDataAction) action, data,
134                        draft.message, draft.conversation);
135            }
136        }
137
138        @Override
139        public void onActionFailed(final ActionMonitor monitor,
140                final Action action, final Object data, final Object result) {
141            Assert.fail("Reading draft should not fail");
142        }
143    }
144
145    private ReadDraftDataAction(final Parcel in) {
146        super(in);
147    }
148
149    public static final Parcelable.Creator<ReadDraftDataAction> CREATOR
150            = new Parcelable.Creator<ReadDraftDataAction>() {
151        @Override
152        public ReadDraftDataAction createFromParcel(final Parcel in) {
153            return new ReadDraftDataAction(in);
154        }
155
156        @Override
157        public ReadDraftDataAction[] newArray(final int size) {
158            return new ReadDraftDataAction[size];
159        }
160    };
161
162    @Override
163    public void writeToParcel(final Parcel parcel, final int flags) {
164        writeActionToParcel(parcel, flags);
165    }
166}
167