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 
17 package com.android.messaging.datamodel.action;
18 
19 import android.os.Parcel;
20 import android.os.Parcelable;
21 
22 import com.android.messaging.datamodel.BugleDatabaseOperations;
23 import com.android.messaging.datamodel.DataModel;
24 import com.android.messaging.datamodel.DatabaseWrapper;
25 import com.android.messaging.datamodel.action.ActionMonitor.ActionCompletedListener;
26 import com.android.messaging.datamodel.data.ConversationListItemData;
27 import com.android.messaging.datamodel.data.MessageData;
28 import com.android.messaging.util.Assert;
29 import com.android.messaging.util.Assert.RunsOnMainThread;
30 import com.android.messaging.util.LogUtil;
31 import com.google.common.annotations.VisibleForTesting;
32 
33 public class ReadDraftDataAction extends Action implements Parcelable {
34 
35     /**
36      * Interface for ReadDraftDataAction listeners
37      */
38     public interface ReadDraftDataActionListener {
39         @RunsOnMainThread
onReadDraftDataSucceeded(final ReadDraftDataAction action, final Object data, final MessageData message, final ConversationListItemData conversation)40         abstract void onReadDraftDataSucceeded(final ReadDraftDataAction action,
41                 final Object data, final MessageData message,
42                 final ConversationListItemData conversation);
43         @RunsOnMainThread
onReadDraftDataFailed(final ReadDraftDataAction action, final Object data)44         abstract void onReadDraftDataFailed(final ReadDraftDataAction action, final Object data);
45     }
46 
47     /**
48      * Read draft message and associated data (with listener)
49      */
readDraftData(final String conversationId, final MessageData incomingDraft, final Object data, final ReadDraftDataActionListener listener)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 
ReadDraftDataAction(final String conversationId, final MessageData incomingDraft, final String actionKey)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 
DraftData(final MessageData message, final ConversationListItemData conversation)76         DraftData(final MessageData message, final ConversationListItemData conversation) {
77             this.message = message;
78             this.conversation = conversation;
79         }
80     }
81 
82     @Override
executeAction()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 
ReadDraftDataActionMonitor(final Object data, final ReadDraftDataActionListener completed)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
onActionSucceeded(final ActionMonitor monitor, final Action action, final Object data, final Object result)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
onActionFailed(final ActionMonitor monitor, final Action action, final Object data, final Object result)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 
ReadDraftDataAction(final Parcel in)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
writeToParcel(final Parcel parcel, final int flags)163     public void writeToParcel(final Parcel parcel, final int flags) {
164         writeActionToParcel(parcel, flags);
165     }
166 }
167