12f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian/*
22f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * Copyright (C) 2017 The Android Open Source Project
32f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian *
42f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * Licensed under the Apache License, Version 2.0 (the "License");
52f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * you may not use this file except in compliance with the License.
62f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * You may obtain a copy of the License at
72f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian *
82f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian *      http://www.apache.org/licenses/LICENSE-2.0
92f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian *
102f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * Unless required by applicable law or agreed to in writing, software
112f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * distributed under the License is distributed on an "AS IS" BASIS,
122f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * See the License for the specific language governing permissions and
142f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * limitations under the License
152f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian */
162f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianpackage com.android.dialer.calllog.database;
172f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
182f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.content.ContentProviderOperation;
192f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.content.ContentUris;
202f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.content.ContentValues;
212f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.content.Context;
222f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.content.OperationApplicationException;
232f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.os.RemoteException;
242f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.support.annotation.WorkerThread;
252f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.text.TextUtils;
262f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport com.android.dialer.calllog.database.contract.AnnotatedCallLogContract;
272f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
282f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport com.android.dialer.calllog.datasources.CallLogMutations;
292f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport com.android.dialer.common.Assert;
302f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport com.android.dialer.common.LogUtil;
312f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport java.util.ArrayList;
322f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport java.util.Arrays;
332f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport java.util.Map.Entry;
342f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport javax.inject.Inject;
352f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
362f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian/** Applies {@link CallLogMutations} to the annotated call log. */
372f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianpublic class MutationApplier {
382f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
392f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian  @Inject
402f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian  MutationApplier() {}
412f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
422f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian  /** Applies the provided {@link CallLogMutations} to the annotated call log. */
432f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian  @WorkerThread
442f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian  public void applyToDatabase(CallLogMutations mutations, Context appContext)
452f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      throws RemoteException, OperationApplicationException {
462f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    Assert.isWorkerThread();
472f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
482f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    if (mutations.isEmpty()) {
492f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      return;
502f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    }
512f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
522f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    ArrayList<ContentProviderOperation> operations = new ArrayList<>();
532f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
542f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    if (!mutations.getInserts().isEmpty()) {
552f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      LogUtil.i(
562f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian          "CallLogMutations.applyToDatabase", "inserting %d rows", mutations.getInserts().size());
572f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      for (Entry<Long, ContentValues> entry : mutations.getInserts().entrySet()) {
582f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        long id = entry.getKey();
592f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        ContentValues contentValues = entry.getValue();
602f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        operations.add(
612f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian            ContentProviderOperation.newInsert(
622f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian                    ContentUris.withAppendedId(AnnotatedCallLog.CONTENT_URI, id))
632f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian                .withValues(contentValues)
642f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian                .build());
652f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      }
662f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    }
672f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
682f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    if (!mutations.getUpdates().isEmpty()) {
692f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      LogUtil.i(
702f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian          "CallLogMutations.applyToDatabase", "updating %d rows", mutations.getUpdates().size());
712f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      for (Entry<Long, ContentValues> entry : mutations.getUpdates().entrySet()) {
722f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        long id = entry.getKey();
732f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        ContentValues contentValues = entry.getValue();
742f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        operations.add(
752f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian            ContentProviderOperation.newUpdate(
762f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian                    ContentUris.withAppendedId(AnnotatedCallLog.CONTENT_URI, id))
772f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian                .withValues(contentValues)
782f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian                .build());
792f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      }
802f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    }
812f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
822f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    if (!mutations.getDeletes().isEmpty()) {
832f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      LogUtil.i(
842f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian          "CallLogMutations.applyToDatabase", "deleting %d rows", mutations.getDeletes().size());
852f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      String[] questionMarks = new String[mutations.getDeletes().size()];
862f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      Arrays.fill(questionMarks, "?");
872f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
882f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      String whereClause =
892f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian          (AnnotatedCallLog._ID + " in (") + TextUtils.join(",", questionMarks) + ")";
902f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
912f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      String[] whereArgs = new String[mutations.getDeletes().size()];
922f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      int i = 0;
932f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      for (long id : mutations.getDeletes()) {
942f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        whereArgs[i++] = String.valueOf(id);
952f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      }
962f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
972f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      operations.add(
982f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian          ContentProviderOperation.newDelete(AnnotatedCallLog.CONTENT_URI)
992f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian              .withSelection(whereClause, whereArgs)
1002f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian              .build());
1012f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    }
1022f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
1032f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    appContext.getContentResolver().applyBatch(AnnotatedCallLogContract.AUTHORITY, operations);
1042f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian  }
1052f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian}
106