Home | History | Annotate | Download | only in action
      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 import android.text.TextUtils;
     22 
     23 import com.android.messaging.Factory;
     24 import com.android.messaging.datamodel.BugleDatabaseOperations;
     25 import com.android.messaging.datamodel.DataModel;
     26 import com.android.messaging.datamodel.DatabaseWrapper;
     27 import com.android.messaging.datamodel.action.ActionMonitor.ActionCompletedListener;
     28 import com.android.messaging.datamodel.data.LaunchConversationData;
     29 import com.android.messaging.datamodel.data.ParticipantData;
     30 import com.android.messaging.sms.MmsUtils;
     31 import com.android.messaging.util.Assert;
     32 import com.android.messaging.util.Assert.RunsOnMainThread;
     33 import com.android.messaging.util.LogUtil;
     34 
     35 import java.util.ArrayList;
     36 
     37 /**
     38  * Action used to get or create a conversation for a list of conversation participants.
     39  */
     40 public class GetOrCreateConversationAction extends Action implements Parcelable {
     41     /**
     42      * Interface for GetOrCreateConversationAction listeners
     43      */
     44     public interface GetOrCreateConversationActionListener {
     45         @RunsOnMainThread
     46         abstract void onGetOrCreateConversationSucceeded(final ActionMonitor monitor,
     47                 final Object data, final String conversationId);
     48 
     49         @RunsOnMainThread
     50         abstract void onGetOrCreateConversationFailed(final ActionMonitor monitor,
     51                 final Object data);
     52     }
     53 
     54     public static GetOrCreateConversationActionMonitor getOrCreateConversation(
     55             final ArrayList<ParticipantData> participants, final Object data,
     56             final GetOrCreateConversationActionListener listener) {
     57         final GetOrCreateConversationActionMonitor monitor = new
     58                 GetOrCreateConversationActionMonitor(data, listener);
     59         final GetOrCreateConversationAction action = new GetOrCreateConversationAction(participants,
     60                 monitor.getActionKey());
     61         action.start(monitor);
     62         return monitor;
     63     }
     64 
     65 
     66     public static GetOrCreateConversationActionMonitor getOrCreateConversation(
     67             final String[] recipients, final Object data, final LaunchConversationData listener) {
     68         final ArrayList<ParticipantData> participants = new ArrayList<>();
     69         for (String recipient : recipients) {
     70             recipient = recipient.trim();
     71             if (!TextUtils.isEmpty(recipient)) {
     72                 participants.add(ParticipantData.getFromRawPhoneBySystemLocale(recipient));
     73             } else {
     74                 LogUtil.w(LogUtil.BUGLE_TAG, "getOrCreateConversation hit empty recipient");
     75             }
     76         }
     77         return getOrCreateConversation(participants, data, listener);
     78     }
     79 
     80     private static final String KEY_PARTICIPANTS_LIST = "participants_list";
     81 
     82     private GetOrCreateConversationAction(final ArrayList<ParticipantData> participants,
     83             final String actionKey) {
     84         super(actionKey);
     85         actionParameters.putParcelableArrayList(KEY_PARTICIPANTS_LIST, participants);
     86     }
     87 
     88     /**
     89      * Lookup the conversation or create a new one.
     90      */
     91     @Override
     92     protected Object executeAction() {
     93         final DatabaseWrapper db = DataModel.get().getDatabase();
     94 
     95         // First find the thread id for this list of participants.
     96         final ArrayList<ParticipantData> participants =
     97                 actionParameters.getParcelableArrayList(KEY_PARTICIPANTS_LIST);
     98         BugleDatabaseOperations.sanitizeConversationParticipants(participants);
     99         final ArrayList<String> recipients =
    100                 BugleDatabaseOperations.getRecipientsFromConversationParticipants(participants);
    101 
    102         final long threadId = MmsUtils.getOrCreateThreadId(Factory.get().getApplicationContext(),
    103                 recipients);
    104 
    105         if (threadId < 0) {
    106             LogUtil.w(LogUtil.BUGLE_TAG, "Couldn't create a threadId in SMS db for numbers : " +
    107                     LogUtil.sanitizePII(recipients.toString()));
    108             // TODO: Add a better way to indicate an error from executeAction.
    109             return null;
    110         }
    111 
    112         final String conversationId = BugleDatabaseOperations.getOrCreateConversation(db, threadId,
    113                 false, participants, false, false, null);
    114 
    115         return conversationId;
    116     }
    117 
    118     /**
    119      * A monitor that notifies a listener upon completion
    120      */
    121     public static class GetOrCreateConversationActionMonitor extends ActionMonitor
    122             implements ActionCompletedListener {
    123         private final GetOrCreateConversationActionListener mListener;
    124 
    125         GetOrCreateConversationActionMonitor(final Object data,
    126                 final GetOrCreateConversationActionListener listener) {
    127             super(STATE_CREATED, generateUniqueActionKey("GetOrCreateConversationAction"), data);
    128             setCompletedListener(this);
    129             mListener = listener;
    130         }
    131 
    132         @Override
    133         public void onActionSucceeded(final ActionMonitor monitor,
    134                 final Action action, final Object data, final Object result) {
    135             if (result == null) {
    136                 mListener.onGetOrCreateConversationFailed(monitor, data);
    137             } else {
    138                 mListener.onGetOrCreateConversationSucceeded(monitor, data, (String) result);
    139             }
    140         }
    141 
    142         @Override
    143         public void onActionFailed(final ActionMonitor monitor,
    144                 final Action action, final Object data, final Object result) {
    145             // TODO: Currently onActionFailed is only called if there is an error in
    146             // processing requests, not for errors in the local processing.
    147             Assert.fail("Unreachable");
    148             mListener.onGetOrCreateConversationFailed(monitor, data);
    149         }
    150     }
    151 
    152     private GetOrCreateConversationAction(final Parcel in) {
    153         super(in);
    154     }
    155 
    156     public static final Parcelable.Creator<GetOrCreateConversationAction> CREATOR
    157             = new Parcelable.Creator<GetOrCreateConversationAction>() {
    158         @Override
    159         public GetOrCreateConversationAction createFromParcel(final Parcel in) {
    160             return new GetOrCreateConversationAction(in);
    161         }
    162 
    163         @Override
    164         public GetOrCreateConversationAction[] newArray(final int size) {
    165             return new GetOrCreateConversationAction[size];
    166         }
    167     };
    168 
    169     @Override
    170     public void writeToParcel(final Parcel parcel, final int flags) {
    171         writeActionToParcel(parcel, flags);
    172     }
    173 }
    174