14199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/*
24199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Copyright (C) 2010 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 */
16677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawapackage com.android.vcard.tests.testutils;
174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentProviderOperation;
194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentProviderResult;
204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentValues;
214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.net.Uri;
225f363a8136349b242d243c3c0c14e6d5a065d23fDaisuke Miyakawaimport android.provider.ContactsContract.Data;
235f363a8136349b242d243c3c0c14e6d5a065d23fDaisuke Miyakawaimport android.provider.ContactsContract.RawContacts;
244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.test.mock.MockContentProvider;
254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.text.TextUtils;
264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport junit.framework.TestCase;
284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.ArrayList;
304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Arrays;
314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Collection;
324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.HashMap;
334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.HashSet;
344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Map;
355f363a8136349b242d243c3c0c14e6d5a065d23fDaisuke Miyakawaimport java.util.Map.Entry;
364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Set;
374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.SortedMap;
384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.TreeMap;
394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
401680191a2a208fd61123810a88ce9def83e222baDaisuke Miyakawapublic class ImportTestProvider extends MockContentProvider {
411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private final Map<String, Collection<ContentValues>>
421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mMimeTypeToExpectedContentValues = new HashMap<String, Collection<ContentValues>>();
434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void addExpectedContentValues(ContentValues expectedContentValues) {
454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        final String mimeType = expectedContentValues.getAsString(Data.MIMETYPE);
461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        final Collection<ContentValues> contentValuesCollection;
481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mMimeTypeToExpectedContentValues.containsKey(mimeType)) {
491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa             contentValuesCollection = mMimeTypeToExpectedContentValues.get(mimeType);
501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else {
511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            contentValuesCollection = new ArrayList<ContentValues>();
521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mMimeTypeToExpectedContentValues.put(mimeType, contentValuesCollection);
534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        contentValuesCollection.add(expectedContentValues);
564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    @Override
594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public ContentProviderResult[] applyBatch(
604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            ArrayList<ContentProviderOperation> operations) {
614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (operations == null) {
625f363a8136349b242d243c3c0c14e6d5a065d23fDaisuke Miyakawa            TestCase.fail("There is no operation.");
634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        final int size = operations.size();
664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        ContentProviderResult[] fakeResultArray = new ContentProviderResult[size];
674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        for (int i = 0; i < size; i++) {
684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            Uri uri = Uri.withAppendedPath(RawContacts.CONTENT_URI, String.valueOf(i));
694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            fakeResultArray[i] = new ContentProviderResult(uri);
704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        for (int i = 0; i < size; i++) {
734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            ContentProviderOperation operation = operations.get(i);
744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            ContentValues contentValues = operation.resolveValueBackReferences(
754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    fakeResultArray, i);
764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        for (int i = 0; i < size; i++) {
784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            ContentProviderOperation operation = operations.get(i);
794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            ContentValues actualContentValues = operation.resolveValueBackReferences(
804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    fakeResultArray, i);
814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final Uri uri = operation.getUri();
824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (uri.equals(RawContacts.CONTENT_URI)) {
835f363a8136349b242d243c3c0c14e6d5a065d23fDaisuke Miyakawa                TestCase.assertNull(actualContentValues.get(RawContacts.ACCOUNT_NAME));
845f363a8136349b242d243c3c0c14e6d5a065d23fDaisuke Miyakawa                TestCase.assertNull(actualContentValues.get(RawContacts.ACCOUNT_TYPE));
854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else if (uri.equals(Data.CONTENT_URI)) {
864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                final String mimeType = actualContentValues.getAsString(Data.MIMETYPE);
871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (!mMimeTypeToExpectedContentValues.containsKey(mimeType)) {
881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    TestCase.fail("Unregistered MimeType " + mimeType);
894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // Remove data meaningless in this unit tests.
914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // Specifically, Data.DATA1 - DATA7 are set to null or empty String
924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // regardless of the input, but it may change depending on how
934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // resolver-related code handles it.
944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // Here, we ignore these implementation-dependent specs and
954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // just check whether vCard importer correctly inserts rellevent data.
964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                Set<String> keyToBeRemoved = new HashSet<String>();
974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                for (Entry<String, Object> entry : actualContentValues.valueSet()) {
984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    Object value = entry.getValue();
994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    if (value == null || TextUtils.isEmpty(value.toString())) {
1004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        keyToBeRemoved.add(entry.getKey());
1014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
1024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
1034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                for (String key: keyToBeRemoved) {
1044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    actualContentValues.remove(key);
1054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
1064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                /* for testing
1074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                Log.d("@@@",
1084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        String.format("MimeType: %s, data: %s",
1094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                                mimeType, actualContentValues.toString())); */
1104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // Remove RAW_CONTACT_ID entry just for safety, since we do not care
1114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // how resolver-related code handles the entry in this unit test,
1124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (actualContentValues.containsKey(Data.RAW_CONTACT_ID)) {
1134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    actualContentValues.remove(Data.RAW_CONTACT_ID);
1144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
1154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                final Collection<ContentValues> contentValuesCollection =
1164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    mMimeTypeToExpectedContentValues.get(mimeType);
1174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (contentValuesCollection.isEmpty()) {
1185f363a8136349b242d243c3c0c14e6d5a065d23fDaisuke Miyakawa                    TestCase.fail("ContentValues for MimeType " + mimeType
1194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            + " is not expected at all (" + actualContentValues + ")");
1204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
1214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                boolean checked = false;
1224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                for (ContentValues expectedContentValues : contentValuesCollection) {
1234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    /*for testing
1244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    Log.d("@@@", "expected: "
1254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            + convertToEasilyReadableString(expectedContentValues));
1264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    Log.d("@@@", "actual  : "
1274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            + convertToEasilyReadableString(actualContentValues));*/
1284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    if (equalsForContentValues(expectedContentValues,
1294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            actualContentValues)) {
1305f363a8136349b242d243c3c0c14e6d5a065d23fDaisuke Miyakawa                        TestCase.assertTrue(contentValuesCollection.remove(expectedContentValues));
1314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        checked = true;
1324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        break;
1334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
1344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
1354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (!checked) {
1364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    final StringBuilder builder = new StringBuilder();
1374560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa                    builder.append("\n");
1384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    builder.append("Unexpected: ");
1394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    builder.append(convertToEasilyReadableString(actualContentValues));
1404560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa                    builder.append("\n");
1414560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa                    builder.append("Expected  : ");
1424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    for (ContentValues expectedContentValues : contentValuesCollection) {
1434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        builder.append(convertToEasilyReadableString(expectedContentValues));
1444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
1455f363a8136349b242d243c3c0c14e6d5a065d23fDaisuke Miyakawa                    TestCase.fail(builder.toString());
1464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
1474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
1485f363a8136349b242d243c3c0c14e6d5a065d23fDaisuke Miyakawa                TestCase.fail("Unexpected Uri has come: " + uri);
1494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
1504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }  // for (int i = 0; i < size; i++) {
1514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return fakeResultArray;
1524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
15448dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    /**
15548dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa     * Checks all expected ContentValues are consumed during import.
15648dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa     */
1574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void verify() {
1584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        StringBuilder builder = new StringBuilder();
1594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        for (Collection<ContentValues> contentValuesCollection :
1604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                mMimeTypeToExpectedContentValues.values()) {
1614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            for (ContentValues expectedContentValues: contentValuesCollection) {
1624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                builder.append(convertToEasilyReadableString(expectedContentValues));
1634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                builder.append("\n");
1644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
1654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (builder.length() > 0) {
1674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final String failMsg =
1684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                "There is(are) remaining expected ContentValues instance(s): \n"
1694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    + builder.toString();
1705f363a8136349b242d243c3c0c14e6d5a065d23fDaisuke Miyakawa            TestCase.fail(failMsg);
1714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
1754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * Utility method to print ContentValues whose content is printed with sorted keys.
1764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
1774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private String convertToEasilyReadableString(ContentValues contentValues) {
1784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (contentValues == null) {
1794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return "null";
1804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        String mimeTypeValue = "";
1824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        SortedMap<String, String> sortedMap = new TreeMap<String, String>();
1834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        for (Entry<String, Object> entry : contentValues.valueSet()) {
1844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final String key = entry.getKey();
1854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final Object value = entry.getValue();
1864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final String valueString = (value != null ? value.toString() : null);
1874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (Data.MIMETYPE.equals(key)) {
1884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                mimeTypeValue = valueString;
1894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
1905f363a8136349b242d243c3c0c14e6d5a065d23fDaisuke Miyakawa                TestCase.assertNotNull(key);
1914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                sortedMap.put(key, valueString);
1924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
1934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        StringBuilder builder = new StringBuilder();
1954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        builder.append(Data.MIMETYPE);
1964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        builder.append('=');
1974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        builder.append(mimeTypeValue);
1984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        for (Entry<String, String> entry : sortedMap.entrySet()) {
1994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final String key = entry.getKey();
2004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final String value = entry.getValue();
2014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.append(' ');
2024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.append(key);
2034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.append("=\"");
2044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.append(value);
2054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.append('"');
2064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
2074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return builder.toString();
2084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
2094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
2104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private static boolean equalsForContentValues(
2114560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            final ContentValues expected, final ContentValues actual) {
2124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (expected == actual) {
2134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return true;
2144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (expected == null || actual == null || expected.size() != actual.size()) {
2154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return false;
2164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
2174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
2184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        for (Entry<String, Object> entry : expected.valueSet()) {
2194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final String key = entry.getKey();
2204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final Object value = entry.getValue();
2214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (!actual.containsKey(key)) {
2224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return false;
2234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
2244560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            // Type mismatch usuall happens as importer doesn't care the type of each value.
2254560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            // For example, variable type might be Integer when importing the type of TEL,
2264560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            // while variable type would be String when importing the type of RELATION.
2274560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            final Object actualValue = actual.get(key);
2284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (value instanceof byte[]) {
2294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (!Arrays.equals((byte[])value, (byte[])actualValue)) {
2304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    byte[] e = (byte[])value;
2314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    byte[] a = (byte[])actualValue;
2324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    return false;
2334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
2344560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            } else if (!value.equals(actualValue) &&
2354560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa                    !value.toString().equals(actualValue.toString())) {
2364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return false;
2374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
2384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
2394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return true;
2404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
2414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa}