14199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/*
24199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Copyright (C) 2009 The Android Open Source Project
34199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa *
44199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License");
54199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * you may not use this file except in compliance with the License.
64199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * You may obtain a copy of the License at
74199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa *
84199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa *      http://www.apache.org/licenses/LICENSE-2.0
94199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa *
104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Unless required by applicable law or agreed to in writing, software
114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS,
124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * See the License for the specific language governing permissions and
144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * limitations under the License.
154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */
164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapackage com.android.vcard;
174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
18f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawaimport android.content.ContentProviderOperation;
19f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawaimport android.content.ContentProviderResult;
204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentResolver;
21f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawaimport android.content.OperationApplicationException;
224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.net.Uri;
23f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawaimport android.os.RemoteException;
24f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawaimport android.provider.ContactsContract;
254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.Log;
264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.ArrayList;
284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/**
304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <P>
314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * {@link VCardEntryHandler} implementation which commits the entry to ContentResolver.
324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </P>
334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <P>
344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Note:<BR />
354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Each vCard may contain big photo images encoded by BASE64,
364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * If we store all vCard entries in memory, OutOfMemoryError may be thrown.
374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Thus, this class push each VCard entry into ContentResolver immediately.
384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </P>
394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */
404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapublic class VCardEntryCommitter implements VCardEntryHandler {
4102117b3d19787ff65486b9f9db8abd338ae4c9f9Daisuke Miyakawa    public static String LOG_TAG = VCardConstants.LOG_TAG;
424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private final ContentResolver mContentResolver;
444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private long mTimeToCommit;
45f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa    private int mCounter;
46f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa    private ArrayList<ContentProviderOperation> mOperationList;
4702117b3d19787ff65486b9f9db8abd338ae4c9f9Daisuke Miyakawa    private final ArrayList<Uri> mCreatedUris = new ArrayList<Uri>();
484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public VCardEntryCommitter(ContentResolver resolver) {
504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mContentResolver = resolver;
514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
53f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa    @Override
544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void onStart() {
554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
57f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa    @Override
584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void onEnd() {
59f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        if (mOperationList != null) {
60f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            mCreatedUris.add(pushIntoContentResolver(mOperationList));
61f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        }
62f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa
634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (VCardConfig.showPerformanceLog()) {
644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            Log.d(LOG_TAG, String.format("time to commit entries: %d ms", mTimeToCommit));
654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
68f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa    @Override
694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void onEntryCreated(final VCardEntry vcardEntry) {
70f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        final long start = System.currentTimeMillis();
71f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        mOperationList = vcardEntry.constructInsertOperations(mContentResolver, mOperationList);
72f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        mCounter++;
73f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        if (mCounter >= 20) {
74f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            mCreatedUris.add(pushIntoContentResolver(mOperationList));
75f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            mCounter = 0;
76f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            mOperationList = null;
77f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        }
784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mTimeToCommit += System.currentTimeMillis() - start;
794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
81f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa    private Uri pushIntoContentResolver(ArrayList<ContentProviderOperation> operationList) {
82f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        try {
83f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            final ContentProviderResult[] results = mContentResolver.applyBatch(
84f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa                    ContactsContract.AUTHORITY, operationList);
85f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa
86f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            // the first result is always the raw_contact. return it's uri so
87f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            // that it can be found later. do null checking for badly behaving
88f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            // ContentResolvers
89f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            return ((results == null || results.length == 0 || results[0] == null)
90f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa                            ? null : results[0].uri);
91f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        } catch (RemoteException e) {
92f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            Log.e(LOG_TAG, String.format("%s: %s", e.toString(), e.getMessage()));
93f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            return null;
94f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        } catch (OperationApplicationException e) {
95f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            Log.e(LOG_TAG, String.format("%s: %s", e.toString(), e.getMessage()));
96f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            return null;
97f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        }
98f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa    }
99f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa
1004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
1014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * Returns the list of created Uris. This list should not be modified by the caller as it is
1024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * not a clone.
1034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
1044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa   public ArrayList<Uri> getCreatedUris() {
1054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mCreatedUris;
1064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa}