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 */
161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapackage com.android.vcard;
184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
199919ad2126c06dbf2eb54a11e6158f87f316bc22Daisuke Miyakawaimport com.android.vcard.VCardUtils.PhoneNumberUtilsPort;
209919ad2126c06dbf2eb54a11e6158f87f316bc22Daisuke Miyakawa
214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.accounts.Account;
224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentProviderOperation;
234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentResolver;
244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.net.Uri;
251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport android.provider.ContactsContract;
264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Email;
274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Event;
284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.GroupMembership;
294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Im;
304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Nickname;
314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Note;
324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Organization;
334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Phone;
344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Photo;
3588d0f1ef715f2e1209eba5d175b1b71c556fa8b0Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.SipAddress;
364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.StructuredName;
374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Website;
3988d0f1ef715f2e1209eba5d175b1b71c556fa8b0Daisuke Miyakawaimport android.provider.ContactsContract.Contacts;
4088d0f1ef715f2e1209eba5d175b1b71c556fa8b0Daisuke Miyakawaimport android.provider.ContactsContract.Data;
4188d0f1ef715f2e1209eba5d175b1b71c556fa8b0Daisuke Miyakawaimport android.provider.ContactsContract.RawContacts;
4295e66b00988bc16ecc17df31e47c873b2554b8ccinshikimport android.telephony.PhoneNumberUtils;
434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.text.TextUtils;
444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.Log;
454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.ArrayList;
474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Arrays;
484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Collection;
494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Collections;
504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.HashMap;
514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.List;
524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Map;
534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/**
551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * Represents one vCard entry, which should start with "BEGIN:VCARD" and end
561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * with "END:VCARD". This class is for bridging between real vCard data and
571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * Android's {@link ContactsContract}, which means some aspects of vCard are
581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * dropped before this object being constructed. Raw vCard data should be first
591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * supplied with {@link #addProperty(VCardProperty)}. After supplying all data,
601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * user should call {@link #consolidateFields()} to prepare some additional
611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * information which is constructable from supplied raw data. TODO: preserve raw
621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * data using {@link VCardProperty}. If it may just waste memory, this at least
631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * should contain them when it cannot convert vCard as a string to Android's
641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * Contacts representation. Those raw properties should _not_ be used for
651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * {@link #isIgnorable()}.
664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */
674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapublic class VCardEntry {
6802117b3d19787ff65486b9f9db8abd338ae4c9f9Daisuke Miyakawa    private static final String LOG_TAG = VCardConstants.LOG_TAG;
694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
7048dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    private static final int DEFAULT_ORGANIZATION_TYPE = Organization.TYPE_WORK;
714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private static final Map<String, Integer> sImMap = new HashMap<String, Integer>();
734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    static {
754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.PROPERTY_X_AIM, Im.PROTOCOL_AIM);
764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.PROPERTY_X_MSN, Im.PROTOCOL_MSN);
774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.PROPERTY_X_YAHOO, Im.PROTOCOL_YAHOO);
784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.PROPERTY_X_ICQ, Im.PROTOCOL_ICQ);
794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.PROPERTY_X_JABBER, Im.PROTOCOL_JABBER);
804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.PROPERTY_X_SKYPE_USERNAME, Im.PROTOCOL_SKYPE);
814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.PROPERTY_X_GOOGLE_TALK, Im.PROTOCOL_GOOGLE_TALK);
824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.ImportOnly.PROPERTY_X_GOOGLE_TALK_WITH_SPACE,
834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                Im.PROTOCOL_GOOGLE_TALK);
844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public enum EntryLabel {
871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        NAME,
881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        PHONE,
891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        EMAIL,
901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        POSTAL_ADDRESS,
911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        ORGANIZATION,
921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        IM,
931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        PHOTO,
941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        WEBSITE,
951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        SIP,
961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        NICKNAME,
971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        NOTE,
981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        BIRTHDAY,
991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        ANNIVERSARY,
1001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        ANDROID_CUSTOM
1011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static interface EntryElement {
1041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // Also need to inherit toString(), equals().
1051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel();
1061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
1081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex);
1091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty();
1111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    // TODO: vCard 4.0 logically has multiple formatted names and we need to
1141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    // select the most preferable one using PREF parameter.
1151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    //
1161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    // e.g. (based on rev.13)
1171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    // FN;PREF=1:John M. Doe
1181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    // FN;PREF=2:John Doe
1191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    // FN;PREF=3;John
1201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class NameData implements EntryElement {
1211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mFamily;
1221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mGiven;
1231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mMiddle;
1241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mPrefix;
1251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mSuffix;
1261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // Used only when no family nor given name is found.
1281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mFormatted;
1291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mPhoneticFamily;
1311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mPhoneticGiven;
1321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mPhoneticMiddle;
1331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // For "SORT-STRING" in vCard 3.0.
135517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        private String mSortString;
1361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
1381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * Not in vCard but for {@link StructuredName#DISPLAY_NAME}. This field
1391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * is constructed by VCardEntry on demand. Consider using
1401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * {@link VCardEntry#getDisplayName()}.
1411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
1421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // This field should reflect the other Elem fields like Email,
1431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // PostalAddress, etc., while
1441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // This is static class which cannot see other data. Thus we ask
1451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // VCardEntry to populate it.
1461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String displayName;
1471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean emptyStructuredName() {
1491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mFamily) && TextUtils.isEmpty(mGiven)
1501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.isEmpty(mMiddle) && TextUtils.isEmpty(mPrefix)
1511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.isEmpty(mSuffix);
1521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
1531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean emptyPhoneticStructuredName() {
1551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mPhoneticFamily) && TextUtils.isEmpty(mPhoneticGiven)
1561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.isEmpty(mPhoneticMiddle);
1571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
1581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
1611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
1621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
1631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
1641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(StructuredName.RAW_CONTACT_ID, backReferenceIndex);
1651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
1661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mGiven)) {
1681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.GIVEN_NAME, mGiven);
1691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mFamily)) {
1711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.FAMILY_NAME, mFamily);
1721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mMiddle)) {
1741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.MIDDLE_NAME, mMiddle);
1751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mPrefix)) {
1771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.PREFIX, mPrefix);
1781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mSuffix)) {
1801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.SUFFIX, mSuffix);
1811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            boolean phoneticNameSpecified = false;
1841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mPhoneticGiven)) {
1861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.PHONETIC_GIVEN_NAME, mPhoneticGiven);
1871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                phoneticNameSpecified = true;
1881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mPhoneticFamily)) {
1901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.PHONETIC_FAMILY_NAME, mPhoneticFamily);
1911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                phoneticNameSpecified = true;
1921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mPhoneticMiddle)) {
1941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.PHONETIC_MIDDLE_NAME, mPhoneticMiddle);
1951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                phoneticNameSpecified = true;
1961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // SORT-STRING is used only when phonetic names aren't specified in
1991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // the original vCard.
2001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!phoneticNameSpecified) {
201517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                builder.withValue(StructuredName.PHONETIC_GIVEN_NAME, mSortString);
2021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
2031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredName.DISPLAY_NAME, displayName);
2051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
2061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
2091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
2101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return (TextUtils.isEmpty(mFamily) && TextUtils.isEmpty(mMiddle)
2111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.isEmpty(mGiven) && TextUtils.isEmpty(mPrefix)
2121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.isEmpty(mSuffix) && TextUtils.isEmpty(mFormatted)
2131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.isEmpty(mPhoneticFamily) && TextUtils.isEmpty(mPhoneticMiddle)
214517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.isEmpty(mPhoneticGiven) && TextUtils.isEmpty(mSortString));
2151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
2181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
2191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
2201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
2211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
2221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof NameData)) {
2231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
2241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
2251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            NameData nameData = (NameData) obj;
2261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return (TextUtils.equals(mFamily, nameData.mFamily)
2281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mMiddle, nameData.mMiddle)
2291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mGiven, nameData.mGiven)
2301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mPrefix, nameData.mPrefix)
2311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mSuffix, nameData.mSuffix)
2321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mFormatted, nameData.mFormatted)
2331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mPhoneticFamily, nameData.mPhoneticFamily)
2341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mPhoneticMiddle, nameData.mPhoneticMiddle)
235517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.equals(mPhoneticGiven, nameData.mPhoneticGiven)
236517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.equals(mSortString, nameData.mSortString));
237517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
238517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
239517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
240517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
241517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            final String[] hashTargets = new String[] {mFamily, mMiddle, mGiven, mPrefix, mSuffix,
242517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    mFormatted, mPhoneticFamily, mPhoneticMiddle,
243517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    mPhoneticGiven, mSortString};
244517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = 0;
245517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            for (String hashTarget : hashTargets) {
246517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                hash = hash * 31 + (hashTarget != null ? hashTarget.hashCode() : 0);
247517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            }
248517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
2491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
2521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
2531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return String.format("family: %s, given: %s, middle: %s, prefix: %s, suffix: %s",
2541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mFamily, mGiven, mMiddle, mPrefix, mSuffix);
2551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
2581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final EntryLabel getEntryLabel() {
2591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.NAME;
2601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getFamily() {
2631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mFamily;
2641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getMiddle() {
2671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mMiddle;
2681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getGiven() {
2711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mGiven;
2721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getPrefix() {
2751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mPrefix;
2761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getSuffix() {
2791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mSuffix;
2801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getFormatted() {
2831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mFormatted;
2841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
286517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public String getSortString() {
287517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return mSortString;
288517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
289517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
2901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /** @hide Just for testing. */
2911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void setFamily(String family) { mFamily = family; }
2921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /** @hide Just for testing. */
2931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void setMiddle(String middle) { mMiddle = middle; }
2941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /** @hide Just for testing. */
2951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void setGiven(String given) { mGiven = given; }
2961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /** @hide Just for testing. */
2971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void setPrefix(String prefix) { mPrefix = prefix; }
2981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /** @hide Just for testing. */
2991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void setSuffix(String suffix) { mSuffix = suffix; }
3001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
3011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class PhoneData implements EntryElement {
3031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mNumber;
3041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mType;
3051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mLabel;
3061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // isPrimary is (not final but) changable, only when there's no
3081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // appropriate one existing
3094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // in the original VCard.
3101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private boolean mIsPrimary;
3111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public PhoneData(String data, int type, String label, boolean isPrimary) {
3131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNumber = data;
3141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mType = type;
3151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mLabel = label;
3161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mIsPrimary = isPrimary;
3171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
3181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
3201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
3211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
3221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
3231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
3241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Phone.RAW_CONTACT_ID, backReferenceIndex);
3251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
3261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Phone.TYPE, mType);
3281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mType == Phone.TYPE_CUSTOM) {
3291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Phone.LABEL, mLabel);
3301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
3311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Phone.NUMBER, mNumber);
3321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mIsPrimary) {
3331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Phone.IS_PRIMARY, 1);
3341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
3351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
3361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
3371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
3391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
3401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mNumber);
3414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
3424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
3434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
3444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public boolean equals(Object obj) {
3451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
3461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
3471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
3484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (!(obj instanceof PhoneData)) {
3494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return false;
3504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
3511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            PhoneData phoneData = (PhoneData) obj;
3521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return (mType == phoneData.mType
3531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mNumber, phoneData.mNumber)
3541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mLabel, phoneData.mLabel)
3551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && (mIsPrimary == phoneData.mIsPrimary));
3564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
3574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
3584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
359517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
360517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mType;
361517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mNumber != null ? mNumber.hashCode() : 0);
362517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mLabel != null ? mLabel.hashCode() : 0);
363517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
364517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
365517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
366517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
367517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
3684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public String toString() {
3691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return String.format("type: %d, data: %s, label: %s, isPrimary: %s", mType, mNumber,
3701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mLabel, mIsPrimary);
3711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
3721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
3741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final EntryLabel getEntryLabel() {
3751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.PHONE;
3761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
3771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getNumber() {
3791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mNumber;
3801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
3811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public int getType() {
3831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mType;
3841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
3851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getLabel() {
3871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mLabel;
3881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
3891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isPrimary() {
3911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mIsPrimary;
3924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
3934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
3944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
3951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class EmailData implements EntryElement {
3961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mAddress;
3971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mType;
3984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // Used only when TYPE is TYPE_CUSTOM.
3991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mLabel;
4001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final boolean mIsPrimary;
4011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EmailData(String data, int type, String label, boolean isPrimary) {
4031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mType = type;
4041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mAddress = data;
4051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mLabel = label;
4061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mIsPrimary = isPrimary;
4071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
4081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
4101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
4111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
4121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
4131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
4141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Email.RAW_CONTACT_ID, backReferenceIndex);
4151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
4161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Email.TYPE, mType);
4181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mType == Email.TYPE_CUSTOM) {
4191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Email.LABEL, mLabel);
4201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
4211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Email.DATA, mAddress);
4221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mIsPrimary) {
4231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Data.IS_PRIMARY, 1);
4241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
4251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
4261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
4271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
4291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
4301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mAddress);
4314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
4324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
4334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
4344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public boolean equals(Object obj) {
4351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
4361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
4371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
4384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (!(obj instanceof EmailData)) {
4394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return false;
4404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
4411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            EmailData emailData = (EmailData) obj;
4421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return (mType == emailData.mType
4431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mAddress, emailData.mAddress)
4441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mLabel, emailData.mLabel)
4451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && (mIsPrimary == emailData.mIsPrimary));
4464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
4474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
4484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
449517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
450517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mType;
451517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mAddress != null ? mAddress.hashCode() : 0);
452517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mLabel != null ? mLabel.hashCode() : 0);
453517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
454517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
455517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
456517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
457517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
4584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public String toString() {
4591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return String.format("type: %d, data: %s, label: %s, isPrimary: %s", mType, mAddress,
4601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mLabel, mIsPrimary);
4611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
4621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
4641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final EntryLabel getEntryLabel() {
4651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.EMAIL;
4661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
4671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getAddress() {
4691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mAddress;
4701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
4711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public int getType() {
4731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mType;
4741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
4751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getLabel() {
4771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mLabel;
4781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
4791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isPrimary() {
4811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mIsPrimary;
4824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
4834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
4844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
4851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class PostalData implements EntryElement {
4864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // Determined by vCard specification.
4874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // - PO Box, Extended Addr, Street, Locality, Region, Postal Code, Country Name
4881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private static final int ADDR_MAX_DATA_SIZE = 7;
4891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mPobox;
4901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mExtendedAddress;
4911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mStreet;
4921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mLocalty;
4931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mRegion;
4941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mPostalCode;
4951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mCountry;
4961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mType;
4971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mLabel;
4981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private boolean mIsPrimary;
4991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
5001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /** We keep this for {@link StructuredPostal#FORMATTED_ADDRESS} */
5011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // TODO: need better way to construct formatted address.
5021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private int mVCardType;
5031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
5041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public PostalData(String pobox, String extendedAddress, String street, String localty,
5051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                String region, String postalCode, String country, int type, String label,
5061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                boolean isPrimary, int vcardType) {
5071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mType = type;
5081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mPobox = pobox;
5091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mExtendedAddress = extendedAddress;
5101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mStreet = street;
5111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mLocalty = localty;
5121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mRegion = region;
5131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mPostalCode = postalCode;
5141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mCountry = country;
5151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mLabel = label;
5161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mIsPrimary = isPrimary;
5171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mVCardType = vcardType;
5181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
5191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
5201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
5211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * Accepts raw propertyValueList in vCard and constructs PostalData.
5221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
5231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public static PostalData constructPostalData(final List<String> propValueList,
5241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final int type, final String label, boolean isPrimary, int vcardType) {
5251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final String[] dataArray = new String[ADDR_MAX_DATA_SIZE];
5264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
5274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            int size = propValueList.size();
5284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (size > ADDR_MAX_DATA_SIZE) {
5294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                size = ADDR_MAX_DATA_SIZE;
5304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
5314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
5324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // adr-value = 0*6(text-value ";") text-value
5331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // ; PO Box, Extended Address, Street, Locality, Region, Postal Code, Country Name
5344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            //
5354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // Use Iterator assuming List may be LinkedList, though actually it is
5364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // always ArrayList in the current implementation.
5374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            int i = 0;
5384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            for (String addressElement : propValueList) {
5394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                dataArray[i] = addressElement;
5404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (++i >= size) {
5414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    break;
5424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
5434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
5444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            while (i < ADDR_MAX_DATA_SIZE) {
5454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                dataArray[i++] = null;
5464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
5474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
5481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return new PostalData(dataArray[0], dataArray[1], dataArray[2], dataArray[3],
5491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    dataArray[4], dataArray[5], dataArray[6], type, label, isPrimary, vcardType);
5504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
5514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
5524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
5531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
5541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
5551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
5561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
5571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(StructuredPostal.RAW_CONTACT_ID, backReferenceIndex);
5581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE);
5591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
5601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.TYPE, mType);
5611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mType == StructuredPostal.TYPE_CUSTOM) {
5621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredPostal.LABEL, mLabel);
5634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
5641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
5651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final String streetString;
5661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (TextUtils.isEmpty(mStreet)) {
5671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (TextUtils.isEmpty(mExtendedAddress)) {
5681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    streetString = null;
5691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                } else {
5701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    streetString = mExtendedAddress;
5711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
5721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            } else {
5731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (TextUtils.isEmpty(mExtendedAddress)) {
5741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    streetString = mStreet;
5751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                } else {
5761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    streetString = mStreet + " " + mExtendedAddress;
5771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
5781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
5791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.POBOX, mPobox);
5801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.STREET, streetString);
5811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.CITY, mLocalty);
5821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.REGION, mRegion);
5831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.POSTCODE, mPostalCode);
5841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.COUNTRY, mCountry);
5851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
5861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.FORMATTED_ADDRESS, getFormattedAddress(mVCardType));
5871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mIsPrimary) {
5881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Data.IS_PRIMARY, 1);
5891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
5901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
5914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
5924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
5934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public String getFormattedAddress(final int vcardType) {
5944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            StringBuilder builder = new StringBuilder();
5954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            boolean empty = true;
5961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final String[] dataArray = new String[] {
5971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mPobox, mExtendedAddress, mStreet, mLocalty, mRegion, mPostalCode, mCountry
5981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            };
5994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (VCardConfig.isJapaneseDevice(vcardType)) {
6004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // In Japan, the order is reversed.
6014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                for (int i = ADDR_MAX_DATA_SIZE - 1; i >= 0; i--) {
6024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    String addressPart = dataArray[i];
6034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    if (!TextUtils.isEmpty(addressPart)) {
6044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        if (!empty) {
6054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            builder.append(' ');
6064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        } else {
6074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            empty = false;
6084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        }
6094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        builder.append(addressPart);
6104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
6114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
6124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
6134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                for (int i = 0; i < ADDR_MAX_DATA_SIZE; i++) {
6144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    String addressPart = dataArray[i];
6154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    if (!TextUtils.isEmpty(addressPart)) {
6164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        if (!empty) {
6174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            builder.append(' ');
6184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        } else {
6194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            empty = false;
6204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        }
6214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        builder.append(addressPart);
6224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
6234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
6244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
6254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
6264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return builder.toString().trim();
6274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
6284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
6294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
6301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
631517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return (TextUtils.isEmpty(mPobox)
632517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.isEmpty(mExtendedAddress)
633517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.isEmpty(mStreet)
634517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.isEmpty(mLocalty)
635517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.isEmpty(mRegion)
636517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.isEmpty(mPostalCode)
637517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.isEmpty(mCountry));
6381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
6391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
6401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
6411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
6421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
6431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
6441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
6451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof PostalData)) {
6461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
6471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
6481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final PostalData postalData = (PostalData) obj;
6491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return (mType == postalData.mType)
6501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && (mType == StructuredPostal.TYPE_CUSTOM ? TextUtils.equals(mLabel,
651517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                            postalData.mLabel) : true)
652517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && (mIsPrimary == postalData.mIsPrimary)
6531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mPobox, postalData.mPobox)
6541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mExtendedAddress, postalData.mExtendedAddress)
6551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mStreet, postalData.mStreet)
6561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mLocalty, postalData.mLocalty)
6571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mRegion, postalData.mRegion)
6581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mPostalCode, postalData.mPostalCode)
6591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mCountry, postalData.mCountry);
6601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
6611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
6621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
663517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
664517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mType;
665517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mLabel != null ? mLabel.hashCode() : 0);
666517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
667517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
668517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            final String[] hashTargets = new String[] {mPobox, mExtendedAddress, mStreet,
669517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    mLocalty, mRegion, mPostalCode, mCountry};
670517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            for (String hashTarget : hashTargets) {
671517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                hash = hash * 31 + (hashTarget != null ? hashTarget.hashCode() : 0);
672517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            }
673517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
674517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
675517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
676517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
6774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public String toString() {
6781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return String.format("type: %d, label: %s, isPrimary: %s, pobox: %s, "
6791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    + "extendedAddress: %s, street: %s, localty: %s, region: %s, postalCode %s, "
6801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    + "country: %s", mType, mLabel, mIsPrimary, mPobox, mExtendedAddress, mStreet,
6811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mLocalty, mRegion, mPostalCode, mCountry);
6821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
6831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
6841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
6851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final EntryLabel getEntryLabel() {
6861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.POSTAL_ADDRESS;
6871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
6881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
6891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getPobox() {
6901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mPobox;
6911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
6921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
6931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getExtendedAddress() {
6941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mExtendedAddress;
6951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
6961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
6971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getStreet() {
6981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mStreet;
6991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getLocalty() {
7021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mLocalty;
7031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getRegion() {
7061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mRegion;
7071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getPostalCode() {
7101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mPostalCode;
7111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getCountry() {
7141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mCountry;
7151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public int getType() {
7181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mType;
7191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getLabel() {
7221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mLabel;
7231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isPrimary() {
7261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mIsPrimary;
7274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
7284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
7294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
7301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class OrganizationData implements EntryElement {
7314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // non-final is Intentional: we may change the values since this info is separated into
7321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // two parts in vCard: "ORG" + "TITLE", and we have to cope with each field in different
7331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // timing.
7341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mOrganizationName;
7351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mDepartmentName;
7361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mTitle;
7371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mPhoneticName; // We won't have this in "TITLE" property.
7381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mType;
7391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private boolean mIsPrimary;
7401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public OrganizationData(final String organizationName, final String departmentName,
7421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final String titleName, final String phoneticName, int type,
7434560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa                final boolean isPrimary) {
7441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mType = type;
7451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mOrganizationName = organizationName;
7461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mDepartmentName = departmentName;
7471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mTitle = titleName;
7481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mPhoneticName = phoneticName;
7491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mIsPrimary = isPrimary;
7501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getFormattedString() {
7531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final StringBuilder builder = new StringBuilder();
7541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mOrganizationName)) {
7551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.append(mOrganizationName);
7561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mDepartmentName)) {
7591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (builder.length() > 0) {
7601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    builder.append(", ");
7611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
7621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.append(mDepartmentName);
7631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mTitle)) {
7661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (builder.length() > 0) {
7671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    builder.append(", ");
7681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
7691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.append(mTitle);
7701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return builder.toString();
7731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
7761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
7771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
7781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
7791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
7801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Organization.RAW_CONTACT_ID, backReferenceIndex);
7811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
7821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Organization.TYPE, mType);
7831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mOrganizationName != null) {
7841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Organization.COMPANY, mOrganizationName);
7851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mDepartmentName != null) {
7871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Organization.DEPARTMENT, mDepartmentName);
7881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mTitle != null) {
7901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Organization.TITLE, mTitle);
7911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mPhoneticName != null) {
7931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Organization.PHONETIC_NAME, mPhoneticName);
7941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mIsPrimary) {
7961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Organization.IS_PRIMARY, 1);
7971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
7991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
8021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
8031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mOrganizationName) && TextUtils.isEmpty(mDepartmentName)
8041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mPhoneticName);
8054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
8064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
8074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
8084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public boolean equals(Object obj) {
8091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
8101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
8111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
8124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (!(obj instanceof OrganizationData)) {
8134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return false;
8144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
8151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            OrganizationData organization = (OrganizationData) obj;
8161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return (mType == organization.mType
8171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mOrganizationName, organization.mOrganizationName)
8181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mDepartmentName, organization.mDepartmentName)
8191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mTitle, organization.mTitle)
8201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && (mIsPrimary == organization.mIsPrimary));
8214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
8224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
8231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
824517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
825517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mType;
826517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mOrganizationName != null ? mOrganizationName.hashCode() : 0);
827517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mDepartmentName != null ? mDepartmentName.hashCode() : 0);
828517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mTitle != null ? mTitle.hashCode() : 0);
829517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
830517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
831517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
832517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
833517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
8341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
8351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return String.format(
8361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    "type: %d, organization: %s, department: %s, title: %s, isPrimary: %s", mType,
8371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mOrganizationName, mDepartmentName, mTitle, mIsPrimary);
8381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
8411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final EntryLabel getEntryLabel() {
8421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.ORGANIZATION;
8431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getOrganizationName() {
8461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mOrganizationName;
8471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getDepartmentName() {
8501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mDepartmentName;
8511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getTitle() {
8541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mTitle;
8551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getPhoneticName() {
8581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mPhoneticName;
8591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public int getType() {
8621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mType;
8631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isPrimary() {
8661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mIsPrimary;
8671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
8691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class ImData implements EntryElement {
8711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mAddress;
8721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mProtocol;
8731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mCustomProtocol;
8741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mType;
8751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final boolean mIsPrimary;
8761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public ImData(final int protocol, final String customProtocol, final String address,
8781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final int type, final boolean isPrimary) {
8791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mProtocol = protocol;
8801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mCustomProtocol = customProtocol;
8811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mType = type;
8821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mAddress = address;
8831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mIsPrimary = isPrimary;
8841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
8871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
8881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
8891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
8901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
8911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Im.RAW_CONTACT_ID, backReferenceIndex);
8921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
8931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Im.TYPE, mType);
8941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Im.PROTOCOL, mProtocol);
8951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Im.DATA, mAddress);
8961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mProtocol == Im.PROTOCOL_CUSTOM) {
8971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Im.CUSTOM_PROTOCOL, mCustomProtocol);
8981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
8991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mIsPrimary) {
9001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Data.IS_PRIMARY, 1);
9014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
9021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
9031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
9051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
9061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
9071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mAddress);
9081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
9111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
9121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
9131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
9141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
9151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof ImData)) {
9161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
9171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
9181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            ImData imData = (ImData) obj;
919517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return (mType == imData.mType
920517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && mProtocol == imData.mProtocol
9211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mCustomProtocol, imData.mCustomProtocol)
9221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mAddress, imData.mAddress)
9231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && (mIsPrimary == imData.mIsPrimary));
9241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
927517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
928517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mType;
929517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + mProtocol;
930517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mCustomProtocol != null ? mCustomProtocol.hashCode() : 0);
931517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mAddress != null ? mAddress.hashCode() : 0);
932517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
933517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
934517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
935517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
936517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
9371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
9381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return String.format(
9391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    "type: %d, protocol: %d, custom_protcol: %s, data: %s, isPrimary: %s", mType,
9401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mProtocol, mCustomProtocol, mAddress, mIsPrimary);
9411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
9441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final EntryLabel getEntryLabel() {
9451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.IM;
9461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getAddress() {
9491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mAddress;
9501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
9531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * One of the value available for {@link Im#PROTOCOL}. e.g.
9541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * {@link Im#PROTOCOL_GOOGLE_TALK}
9551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
9561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public int getProtocol() {
9571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mProtocol;
9581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getCustomProtocol() {
9611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mCustomProtocol;
9621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public int getType() {
9651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mType;
9661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isPrimary() {
9691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mIsPrimary;
9701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
9721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class PhotoData implements EntryElement {
9741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // private static final String FORMAT_FLASH = "SWF";
9751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // used when type is not defined in ContactsContract.
9771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mFormat;
9781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final boolean mIsPrimary;
9791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
98087315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa        private final byte[] mBytes;
9811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
982517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        private Integer mHashCode = null;
983517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
9841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public PhotoData(String format, byte[] photoBytes, boolean isPrimary) {
9851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mFormat = format;
98687315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa            mBytes = photoBytes;
9871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mIsPrimary = isPrimary;
9881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
9911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
9921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
9931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
9941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
9951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Photo.RAW_CONTACT_ID, backReferenceIndex);
9961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE);
99787315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa            builder.withValue(Photo.PHOTO, mBytes);
9981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mIsPrimary) {
9991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Photo.IS_PRIMARY, 1);
10001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
10011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
10021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
10051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
100687315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa            return mBytes == null || mBytes.length == 0;
10071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
10101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
10111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
10121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
10131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
10141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof PhotoData)) {
10151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
10161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
10171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            PhotoData photoData = (PhotoData) obj;
10181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return (TextUtils.equals(mFormat, photoData.mFormat)
101987315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa                    && Arrays.equals(mBytes, photoData.mBytes)
10201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && (mIsPrimary == photoData.mIsPrimary));
10211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1024517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1025517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            if (mHashCode != null) {
1026517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                return mHashCode;
1027517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            }
1028517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1029517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mFormat != null ? mFormat.hashCode() : 0;
1030517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31;
103187315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa            if (mBytes != null) {
103287315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa                for (byte b : mBytes) {
1033517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    hash += b;
1034517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                }
1035517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            }
1036517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1037517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
1038517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            mHashCode = hash;
1039517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
1040517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1041517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1042517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
10431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
104487315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa            return String.format("format: %s: size: %d, isPrimary: %s", mFormat, mBytes.length,
10451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mIsPrimary);
10461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
10491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final EntryLabel getEntryLabel() {
10501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.PHOTO;
10511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getFormat() {
10541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mFormat;
10551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public byte[] getBytes() {
105887315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa            return mBytes;
10591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isPrimary() {
10621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mIsPrimary;
10631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
10651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class NicknameData implements EntryElement {
10671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mNickname;
10681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public NicknameData(String nickname) {
10701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNickname = nickname;
10711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
10741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
10751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
10761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
10771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
10781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Nickname.RAW_CONTACT_ID, backReferenceIndex);
10791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Nickname.CONTENT_ITEM_TYPE);
10801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Nickname.TYPE, Nickname.TYPE_DEFAULT);
10811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Nickname.NAME, mNickname);
10821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
10831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
10861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
10871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mNickname);
10881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
10911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
10921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof NicknameData)) {
10931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
10941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
10951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            NicknameData nicknameData = (NicknameData) obj;
10961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.equals(mNickname, nicknameData.mNickname);
10971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1100517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1101517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return mNickname != null ? mNickname.hashCode() : 0;
1102517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1103517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1104517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
11051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
11061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return "nickname: " + mNickname;
11071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
11101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel() {
11111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.NICKNAME;
11121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getNickname() {
11151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mNickname;
11161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
11181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class NoteData implements EntryElement {
11201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final String mNote;
11211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public NoteData(String note) {
11231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNote = note;
11241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
11271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
11281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
11291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
11301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
11311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Note.RAW_CONTACT_ID, backReferenceIndex);
11321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Note.CONTENT_ITEM_TYPE);
11331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Note.NOTE, mNote);
11341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
11351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
11381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
11391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mNote);
11401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
11431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
11441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
11451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
11461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
11471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof NoteData)) {
11481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
11491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
11501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            NoteData noteData = (NoteData) obj;
11511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.equals(mNote, noteData.mNote);
11521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1155517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1156517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return mNote != null ? mNote.hashCode() : 0;
1157517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1158517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1159517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
11601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
11611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return "note: " + mNote;
11621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
11651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel() {
11661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.NOTE;
11671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getNote() {
11701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mNote;
11711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
11731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class WebsiteData implements EntryElement {
11751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mWebsite;
11761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public WebsiteData(String website) {
11781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mWebsite = website;
11791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
11821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
11831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
11841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
11851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
11861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Website.RAW_CONTACT_ID, backReferenceIndex);
11871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Website.CONTENT_ITEM_TYPE);
11881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Website.URL, mWebsite);
11891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // There's no information about the type of URL in vCard.
11901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // We use TYPE_HOMEPAGE for safety.
11911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Website.TYPE, Website.TYPE_HOMEPAGE);
11921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
11931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
11961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
11971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mWebsite);
11981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
12011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
12021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
12031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
12041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
12051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof WebsiteData)) {
12061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
12071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
12081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            WebsiteData websiteData = (WebsiteData) obj;
12091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.equals(mWebsite, websiteData.mWebsite);
12101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1213517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1214517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return mWebsite != null ? mWebsite.hashCode() : 0;
1215517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1216517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1217517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
12181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
12191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return "website: " + mWebsite;
12201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
12231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel() {
12241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.WEBSITE;
12251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getWebsite() {
12281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mWebsite;
12291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
12311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class BirthdayData implements EntryElement {
12331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mBirthday;
12341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public BirthdayData(String birthday) {
12361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBirthday = birthday;
12371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
12401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
12411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
12421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
12431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
12441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Event.RAW_CONTACT_ID, backReferenceIndex);
12451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
12461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Event.START_DATE, mBirthday);
12471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Event.TYPE, Event.TYPE_BIRTHDAY);
12481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
12491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
12521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
12531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mBirthday);
12541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
12571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
12581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
12591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
12601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
12611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof BirthdayData)) {
12621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
12631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
12641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            BirthdayData birthdayData = (BirthdayData) obj;
12651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.equals(mBirthday, birthdayData.mBirthday);
12661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1269517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1270517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return mBirthday != null ? mBirthday.hashCode() : 0;
1271517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1272517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1273517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
12741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
12751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return "birthday: " + mBirthday;
12761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
12791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel() {
12801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.BIRTHDAY;
12811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getBirthday() {
12841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mBirthday;
12851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
12871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class AnniversaryData implements EntryElement {
12891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mAnniversary;
12901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public AnniversaryData(String anniversary) {
12921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mAnniversary = anniversary;
12931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
12961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
12971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
12981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
12991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
13001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Event.RAW_CONTACT_ID, backReferenceIndex);
13011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
13021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Event.START_DATE, mAnniversary);
13031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Event.TYPE, Event.TYPE_ANNIVERSARY);
13041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
13051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
13081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
13091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mAnniversary);
13101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
13131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
13141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
13151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
13161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
13171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof AnniversaryData)) {
13181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
13191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
13201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            AnniversaryData anniversaryData = (AnniversaryData) obj;
13211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.equals(mAnniversary, anniversaryData.mAnniversary);
13221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1325517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1326517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return mAnniversary != null ? mAnniversary.hashCode() : 0;
1327517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1328517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1329517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
13301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
13311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return "anniversary: " + mAnniversary;
13321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
13351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel() {
13361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.ANNIVERSARY;
13371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getAnniversary() { return mAnniversary; }
13401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
13411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class SipData implements EntryElement {
13431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
13441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * Note that schema part ("sip:") is automatically removed. e.g.
13451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * "sip:username:password@host:port" becomes
13461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * "username:password@host:port"
13471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
13481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mAddress;
13491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mType;
13501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mLabel;
13511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final boolean mIsPrimary;
13521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public SipData(String rawSip, int type, String label, boolean isPrimary) {
13541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (rawSip.startsWith("sip:")) {
13551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mAddress = rawSip.substring(4);
13561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            } else {
13571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mAddress = rawSip;
13581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
13591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mType = type;
13601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mLabel = label;
13611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mIsPrimary = isPrimary;
13621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
13651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
13661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
13671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
13681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
13691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(SipAddress.RAW_CONTACT_ID, backReferenceIndex);
13701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, SipAddress.CONTENT_ITEM_TYPE);
13711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(SipAddress.SIP_ADDRESS, mAddress);
13721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(SipAddress.TYPE, mType);
13731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mType == SipAddress.TYPE_CUSTOM) {
13741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(SipAddress.LABEL, mLabel);
13751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
13761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mIsPrimary) {
13771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(SipAddress.IS_PRIMARY, mIsPrimary);
13781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
13791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
13801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
13831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
13841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mAddress);
13851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
13881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
13891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
13901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
13911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
13921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof SipData)) {
13931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
13941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
13951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            SipData sipData = (SipData) obj;
1396517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return (mType == sipData.mType
1397517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.equals(mLabel, sipData.mLabel)
1398517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.equals(mAddress, sipData.mAddress)
1399517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && (mIsPrimary == sipData.mIsPrimary));
1400517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1401517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1402517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
1403517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1404517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mType;
1405517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mLabel != null ? mLabel.hashCode() : 0);
1406517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mAddress != null ? mAddress.hashCode() : 0);
1407517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
1408517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
14091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
14101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
14121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
14131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return "sip: " + mAddress;
14141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
14151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
14171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel() {
14181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.SIP;
14191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
14201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
14221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * @return Address part of the sip data. The schema ("sip:") isn't contained here.
14231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
14241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getAddress() { return mAddress; }
14251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public int getType() { return mType; }
14261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getLabel() { return mLabel; }
14271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
14281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    /**
14301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * Some Contacts data in Android cannot be converted to vCard
14311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * representation. VCardEntry preserves those data using this class.
14321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     */
14331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class AndroidCustomData implements EntryElement {
14341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mMimeType;
14351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final List<String> mDataList; // 1 .. VCardConstants.MAX_DATA_COLUMN
14371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public AndroidCustomData(String mimeType, List<String> dataList) {
14391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mMimeType = mimeType;
14401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mDataList = dataList;
14411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
14421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public static AndroidCustomData constructAndroidCustomData(List<String> list) {
14441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            String mimeType;
14451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            List<String> dataList;
14461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (list == null) {
14481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mimeType = null;
14491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                dataList = null;
14501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            } else if (list.size() < 2) {
14511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mimeType = list.get(0);
14521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                dataList = null;
14531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            } else {
14541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final int max = (list.size() < VCardConstants.MAX_DATA_COLUMN + 1) ? list.size()
14551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        : VCardConstants.MAX_DATA_COLUMN + 1;
14561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mimeType = list.get(0);
14571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                dataList = list.subList(1, max);
14581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
14591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return new AndroidCustomData(mimeType, dataList);
14611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
14621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
14641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
14651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
14661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
14671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
14681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(GroupMembership.RAW_CONTACT_ID, backReferenceIndex);
14691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, mMimeType);
14701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            for (int i = 0; i < mDataList.size(); i++) {
14711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                String value = mDataList.get(i);
14721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (!TextUtils.isEmpty(value)) {
14731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    // 1-origin
14741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    builder.withValue("data" + (i + 1), value);
14754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
14764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
14771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
14781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
14794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
14801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
14811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
14821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mMimeType) || mDataList == null || mDataList.size() == 0;
14831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
14841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
14861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
14871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
14881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
14891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
14901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof AndroidCustomData)) {
14911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
14921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
14931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            AndroidCustomData data = (AndroidCustomData) obj;
14941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.equals(mMimeType, data.mMimeType)) {
14951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
14961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
14971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mDataList == null) {
14981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return data.mDataList == null;
14991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            } else {
15001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final int size = mDataList.size();
15011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (size != data.mDataList.size()) {
15021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    return false;
15031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
15041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                for (int i = 0; i < size; i++) {
15051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    if (!TextUtils.equals(mDataList.get(i), data.mDataList.get(i))) {
15061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        return false;
15071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    }
15084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
15091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
15104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
15111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
15124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
15131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1514517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1515517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mMimeType != null ? mMimeType.hashCode() : 0;
1516517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            if (mDataList != null) {
1517517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                for (String data : mDataList) {
1518517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    hash = hash * 31 + (data != null ? data.hashCode() : 0);
1519517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                }
1520517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            }
1521517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
1522517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1523517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1524517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
15251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
15261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final StringBuilder builder = new StringBuilder();
15271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.append("android-custom: " + mMimeType + ", data: ");
15281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.append(mDataList == null ? "null" : Arrays.toString(mDataList.toArray()));
15294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return builder.toString();
15304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
15314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
15324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
15331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel() {
15341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.ANDROID_CUSTOM;
15354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
15361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
15371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getMimeType() { return mMimeType; }
15381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public List<String> getDataList() { return mDataList; }
15394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
15404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
15411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private final NameData mNameData = new NameData();
15421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<PhoneData> mPhoneList;
15431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<EmailData> mEmailList;
15441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<PostalData> mPostalList;
15451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<OrganizationData> mOrganizationList;
15461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<ImData> mImList;
15471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<PhotoData> mPhotoList;
15481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<WebsiteData> mWebsiteList;
15491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<SipData> mSipList;
15501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<NicknameData> mNicknameList;
15511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<NoteData> mNoteList;
15521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<AndroidCustomData> mAndroidCustomDataList;
15531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private BirthdayData mBirthday;
15541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private AnniversaryData mAnniversary;
15554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
15561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    /**
15571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * Inner iterator interface.
15581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     */
15591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public interface EntryElementIterator {
15601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationStarted();
15611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
15621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationEnded();
15631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
15641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
15651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * Called when there are one or more {@link EntryElement} instances
15661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * associated with {@link EntryLabel}.
15671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
15681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupStarted(EntryLabel label);
15691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
15701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
15711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * Called after all {@link EntryElement} instances for
15721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * {@link EntryLabel} provided on {@link #onElementGroupStarted(EntryLabel)}
15731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * being processed by {@link #onElement(EntryElement)}
15741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
15751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupEnded();
15761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
15771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
15781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * @return should be true when child wants to continue the operation.
15791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         *         False otherwise.
15801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
15811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean onElement(EntryElement elem);
15821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
15834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
15841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public final void iterateAllData(EntryElementIterator iterator) {
15851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterator.onIterationStarted();
15861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterator.onElementGroupStarted(mNameData.getEntryLabel());
15871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterator.onElement(mNameData);
15881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterator.onElementGroupEnded();
15891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
15901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mPhoneList, iterator);
15911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mEmailList, iterator);
15921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mPostalList, iterator);
15931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mOrganizationList, iterator);
15941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mImList, iterator);
15951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mPhotoList, iterator);
15961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mWebsiteList, iterator);
15971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mSipList, iterator);
15981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mNicknameList, iterator);
15991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mNoteList, iterator);
16001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mAndroidCustomDataList, iterator);
16011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
16021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mBirthday != null) {
16031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElementGroupStarted(mBirthday.getEntryLabel());
16041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElement(mBirthday);
16051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElementGroupEnded();
16061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
16071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mAnniversary != null) {
16081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElementGroupStarted(mAnniversary.getEntryLabel());
16091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElement(mAnniversary);
16101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElementGroupEnded();
16111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
16121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterator.onIterationEnded();
16131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
16141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
16151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private void iterateOneList(List<? extends EntryElement> elemList,
16161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            EntryElementIterator iterator) {
16171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (elemList != null && elemList.size() > 0) {
16181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElementGroupStarted(elemList.get(0).getEntryLabel());
16191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            for (EntryElement elem : elemList) {
16201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                iterator.onElement(elem);
16214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
16221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElementGroupEnded();
16234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
16251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
16261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private class IsIgnorableIterator implements EntryElementIterator {
16271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private boolean mEmpty = true;
16284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
16301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationStarted() {
16314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
16341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationEnded() {
16354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
16381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupStarted(EntryLabel label) {
16394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
16421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupEnded() {
16434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
16461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean onElement(EntryElement elem) {
16471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!elem.isEmpty()) {
16481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mEmpty = false;
16491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                // exit now
16501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
16514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
16521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
16534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
16544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean getResult() {
16571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mEmpty;
16584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
16601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
16611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private class ToStringIterator implements EntryElementIterator {
16621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private StringBuilder mBuilder;
16631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
16641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private boolean mFirstElement;
16654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
16671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationStarted() {
16681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBuilder = new StringBuilder();
16691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBuilder.append("[[hash: " + VCardEntry.this.hashCode() + "\n");
167048dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        }
167148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
16721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
16731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupStarted(EntryLabel label) {
16741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBuilder.append(label.toString() + ": ");
16751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mFirstElement = true;
16764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
16791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean onElement(EntryElement elem) {
16801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!mFirstElement) {
16811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mBuilder.append(", ");
16821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mFirstElement = false;
16831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
16841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBuilder.append("[").append(elem.toString()).append("]");
16851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return true;
16864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
16891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupEnded() {
16901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBuilder.append("\n");
16914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
16941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationEnded() {
16951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBuilder.append("]]\n");
16964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
169748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
169848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        @Override
169948dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        public String toString() {
17001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mBuilder.toString();
170148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        }
17024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
17034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private class InsertOperationConstrutor implements EntryElementIterator {
17051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final List<ContentProviderOperation> mOperationList;
17064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mBackReferenceIndex;
17084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public InsertOperationConstrutor(List<ContentProviderOperation> operationList,
17101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
17111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mOperationList = operationList;
17121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBackReferenceIndex = backReferenceIndex;
17131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
17144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
17161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationStarted() {
17171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
17184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
17201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationEnded() {
17211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
17224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
17241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupStarted(EntryLabel label) {
17251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
17264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
17281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupEnded() {
17291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
17304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
17321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean onElement(EntryElement elem) {
17331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!elem.isEmpty()) {
17341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                elem.constructInsertOperation(mOperationList, mBackReferenceIndex);
17351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
17361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return true;
17371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
17381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
17394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private final int mVCardType;
17414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private final Account mAccount;
17424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
174348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    private List<VCardEntry> mChildren;
174448dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
174548dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
174648dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    public String toString() {
17471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        ToStringIterator iterator = new ToStringIterator();
17481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateAllData(iterator);
17491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return iterator.toString();
175048dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    }
175148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
17524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public VCardEntry() {
17534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        this(VCardConfig.VCARD_TYPE_V21_GENERIC);
17544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
17554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public VCardEntry(int vcardType) {
17574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        this(vcardType, null);
17584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
17594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public VCardEntry(int vcardType, Account account) {
17614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mVCardType = vcardType;
17624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mAccount = account;
17634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
17644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void addPhone(int type, String data, String label, boolean isPrimary) {
17664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mPhoneList == null) {
17674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mPhoneList = new ArrayList<PhoneData>();
17684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
17694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        final StringBuilder builder = new StringBuilder();
177095e66b00988bc16ecc17df31e47c873b2554b8ccinshik        final String trimmed = data.trim();
17714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        final String formattedNumber;
17724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (type == Phone.TYPE_PAGER || VCardConfig.refrainPhoneNumberFormatting(mVCardType)) {
177395e66b00988bc16ecc17df31e47c873b2554b8ccinshik            formattedNumber = trimmed;
17744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
177595e66b00988bc16ecc17df31e47c873b2554b8ccinshik            // TODO: from the view of vCard spec these auto conversions should be removed.
177695e66b00988bc16ecc17df31e47c873b2554b8ccinshik            // Note that some other codes (like the phone number formatter) or modules expect this
177795e66b00988bc16ecc17df31e47c873b2554b8ccinshik            // auto conversion (bug 5178723), so just omitting this code won't be preferable enough
177895e66b00988bc16ecc17df31e47c873b2554b8ccinshik            // (bug 4177894)
177995e66b00988bc16ecc17df31e47c873b2554b8ccinshik            boolean hasPauseOrWait = false;
178095e66b00988bc16ecc17df31e47c873b2554b8ccinshik            final int length = trimmed.length();
17814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            for (int i = 0; i < length; i++) {
178295e66b00988bc16ecc17df31e47c873b2554b8ccinshik                char ch = trimmed.charAt(i);
178395e66b00988bc16ecc17df31e47c873b2554b8ccinshik                // See RFC 3601 and docs for PhoneNumberUtils for more info.
178495e66b00988bc16ecc17df31e47c873b2554b8ccinshik                if (ch == 'p' || ch == 'P') {
178595e66b00988bc16ecc17df31e47c873b2554b8ccinshik                    builder.append(PhoneNumberUtils.PAUSE);
178695e66b00988bc16ecc17df31e47c873b2554b8ccinshik                    hasPauseOrWait = true;
178795e66b00988bc16ecc17df31e47c873b2554b8ccinshik                } else if (ch == 'w' || ch == 'W') {
178895e66b00988bc16ecc17df31e47c873b2554b8ccinshik                    builder.append(PhoneNumberUtils.WAIT);
178995e66b00988bc16ecc17df31e47c873b2554b8ccinshik                    hasPauseOrWait = true;
179095e66b00988bc16ecc17df31e47c873b2554b8ccinshik                } else if (('0' <= ch && ch <= '9') || (i == 0 && ch == '+')) {
17914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    builder.append(ch);
17924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
17934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
179495e66b00988bc16ecc17df31e47c873b2554b8ccinshik            if (!hasPauseOrWait) {
179595e66b00988bc16ecc17df31e47c873b2554b8ccinshik                final int formattingType = VCardUtils.getPhoneNumberFormat(mVCardType);
179695e66b00988bc16ecc17df31e47c873b2554b8ccinshik                formattedNumber = PhoneNumberUtilsPort.formatNumber(
179795e66b00988bc16ecc17df31e47c873b2554b8ccinshik                        builder.toString(), formattingType);
179895e66b00988bc16ecc17df31e47c873b2554b8ccinshik            } else {
179995e66b00988bc16ecc17df31e47c873b2554b8ccinshik                formattedNumber = builder.toString();
180095e66b00988bc16ecc17df31e47c873b2554b8ccinshik            }
18011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
18021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        PhoneData phoneData = new PhoneData(formattedNumber, type, label, isPrimary);
18034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mPhoneList.add(phoneData);
18044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
18054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
18061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private void addSip(String sipData, int type, String label, boolean isPrimary) {
18071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mSipList == null) {
18081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mSipList = new ArrayList<SipData>();
18091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
18101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mSipList.add(new SipData(sipData, type, label, isPrimary));
18111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
18121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
18134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void addNickName(final String nickName) {
18141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mNicknameList == null) {
18151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNicknameList = new ArrayList<NicknameData>();
18164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
18171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mNicknameList.add(new NicknameData(nickName));
18184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
18194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
18201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private void addEmail(int type, String data, String label, boolean isPrimary) {
18214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mEmailList == null) {
18224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mEmailList = new ArrayList<EmailData>();
18234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
18241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mEmailList.add(new EmailData(data, type, label, isPrimary));
18254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
18264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
18271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private void addPostal(int type, List<String> propValueList, String label, boolean isPrimary) {
18284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mPostalList == null) {
18294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mPostalList = new ArrayList<PostalData>(0);
18304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
18311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mPostalList.add(PostalData.constructPostalData(propValueList, type, label, isPrimary,
18321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mVCardType));
18334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
18344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
18354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
183602117b3d19787ff65486b9f9db8abd338ae4c9f9Daisuke Miyakawa     * Should be called via {@link #handleOrgValue(int, List, Map, boolean)} or
18374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * {@link #handleTitleValue(String)}.
18384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
18391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private void addNewOrganization(final String organizationName, final String departmentName,
18401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final String titleName, final String phoneticName, int type, final boolean isPrimary) {
18414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mOrganizationList == null) {
18424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mOrganizationList = new ArrayList<OrganizationData>();
18434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
18441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mOrganizationList.add(new OrganizationData(organizationName, departmentName, titleName,
18451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                phoneticName, type, isPrimary));
18464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
18474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
18481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private static final List<String> sEmptyList = Collections
18491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            .unmodifiableList(new ArrayList<String>(0));
18504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
18514560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa    private String buildSinglePhoneticNameFromSortAsParam(Map<String, Collection<String>> paramMap) {
18524560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        final Collection<String> sortAsCollection = paramMap.get(VCardConstants.PARAM_SORT_AS);
18534560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        if (sortAsCollection != null && sortAsCollection.size() != 0) {
18544560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            if (sortAsCollection.size() > 1) {
18551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                Log.w(LOG_TAG,
18561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        "Incorrect multiple SORT_AS parameters detected: "
18571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                                + Arrays.toString(sortAsCollection.toArray()));
18584560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            }
18591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final List<String> sortNames = VCardUtils.constructListFromValue(sortAsCollection
18601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .iterator().next(), mVCardType);
18614560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            final StringBuilder builder = new StringBuilder();
18624560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            for (final String elem : sortNames) {
18634560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa                builder.append(elem);
18644560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            }
18654560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            return builder.toString();
18664560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        } else {
18674560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            return null;
18684560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        }
18694560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa    }
18704560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa
18714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
18721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * Set "ORG" related values to the appropriate data. If there's more than
18731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * one {@link OrganizationData} objects, this input data are attached to the
18741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * last one which does not have valid values (not including empty but only
18751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * null). If there's no {@link OrganizationData} object, a new
18761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * {@link OrganizationData} is created, whose title is set to null.
18774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
18784560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa    private void handleOrgValue(final int type, List<String> orgList,
18794560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            Map<String, Collection<String>> paramMap, boolean isPrimary) {
18804560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        final String phoneticName = buildSinglePhoneticNameFromSortAsParam(paramMap);
18814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (orgList == null) {
18824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            orgList = sEmptyList;
18834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
18841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        final String organizationName;
18854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        final String departmentName;
18864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        final int size = orgList.size();
18874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        switch (size) {
18881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 0: {
18891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            organizationName = "";
18901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            departmentName = null;
18911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            break;
18921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
18931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 1: {
18941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            organizationName = orgList.get(0);
18951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            departmentName = null;
18961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            break;
18971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
18981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        default: { // More than 1.
18991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            organizationName = orgList.get(0);
19001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // We're not sure which is the correct string for department.
19011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // In order to keep all the data, concatinate the rest of elements.
19021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            StringBuilder builder = new StringBuilder();
19031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            for (int i = 1; i < size; i++) {
19041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (i > 1) {
19051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    builder.append(' ');
19064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
19071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.append(orgList.get(i));
19084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
19091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            departmentName = builder.toString();
19101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
19114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mOrganizationList == null) {
19134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // Create new first organization entry, with "null" title which may be
19144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // added via handleTitleValue().
19151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            addNewOrganization(organizationName, departmentName, null, phoneticName, type,
19161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    isPrimary);
19174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return;
19184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        for (OrganizationData organizationData : mOrganizationList) {
19204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // Not use TextUtils.isEmpty() since ORG was set but the elements might be empty.
19214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // e.g. "ORG;PREF:;" -> Both companyName and departmentName become empty but not null.
19221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (organizationData.mOrganizationName == null
19231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && organizationData.mDepartmentName == null) {
19244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // Probably the "TITLE" property comes before the "ORG" property via
19254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // handleTitleLine().
19261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                organizationData.mOrganizationName = organizationName;
19271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                organizationData.mDepartmentName = departmentName;
19281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                organizationData.mIsPrimary = isPrimary;
19294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return;
19304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
19314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // No OrganizatioData is available. Create another one, with "null" title, which may be
19334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // added via handleTitleValue().
19341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        addNewOrganization(organizationName, departmentName, null, phoneticName, type, isPrimary);
19354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
19364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
19374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
19384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * Set "title" value to the appropriate data. If there's more than one
19391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * OrganizationData objects, this input is attached to the last one which
19401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * does not have valid title value (not including empty but only null). If
19411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * there's no OrganizationData object, a new OrganizationData is created,
19421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * whose company name is set to null.
19434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
19444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void handleTitleValue(final String title) {
19454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mOrganizationList == null) {
19464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // Create new first organization entry, with "null" other info, which may be
19474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // added via handleOrgValue().
19481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            addNewOrganization(null, null, title, null, DEFAULT_ORGANIZATION_TYPE, false);
19494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return;
19504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        for (OrganizationData organizationData : mOrganizationList) {
19521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (organizationData.mTitle == null) {
19531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                organizationData.mTitle = title;
19544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return;
19554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
19564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // No Organization is available. Create another one, with "null" other info, which may be
19584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // added via handleOrgValue().
19591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        addNewOrganization(null, null, title, null, DEFAULT_ORGANIZATION_TYPE, false);
19604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
19614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
19621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private void addIm(int protocol, String customProtocol, String propValue, int type,
19631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            boolean isPrimary) {
19644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mImList == null) {
19654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mImList = new ArrayList<ImData>();
19664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mImList.add(new ImData(protocol, customProtocol, propValue, type, isPrimary));
19684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
19694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
19704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void addNote(final String note) {
19714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mNoteList == null) {
19721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNoteList = new ArrayList<NoteData>(1);
19734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mNoteList.add(new NoteData(note));
19754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
19764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
19774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void addPhotoBytes(String formatName, byte[] photoBytes, boolean isPrimary) {
19784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mPhotoList == null) {
19794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mPhotoList = new ArrayList<PhotoData>(1);
19804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        final PhotoData photoData = new PhotoData(formatName, photoBytes, isPrimary);
19824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mPhotoList.add(photoData);
19834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
19844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
19854560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa    /**
19861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * Tries to extract paramMap, constructs SORT-AS parameter values, and store
19871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * them in appropriate phonetic name variables. This method does not care
19881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * the vCard version. Even when we have SORT-AS parameters in invalid
19891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * versions (i.e. 2.1 and 3.0), we scilently accept them so that we won't
19901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * drop meaningful information. If we had this parameter in the N field of
19911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * vCard 3.0, and the contact data also have SORT-STRING, we will prefer
19921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * SORT-STRING, since it is regitimate property to be understood.
19934560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa     */
19944560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa    private void tryHandleSortAsName(final Map<String, Collection<String>> paramMap) {
19951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (VCardConfig.isVersion30(mVCardType)
19961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                && !(TextUtils.isEmpty(mNameData.mPhoneticFamily)
19971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        && TextUtils.isEmpty(mNameData.mPhoneticMiddle) && TextUtils
19981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        .isEmpty(mNameData.mPhoneticGiven))) {
19994560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            return;
20004560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        }
20014560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa
20024560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        final Collection<String> sortAsCollection = paramMap.get(VCardConstants.PARAM_SORT_AS);
20034560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        if (sortAsCollection != null && sortAsCollection.size() != 0) {
20044560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            if (sortAsCollection.size() > 1) {
20051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                Log.w(LOG_TAG,
20061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        "Incorrect multiple SORT_AS parameters detected: "
20071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                                + Arrays.toString(sortAsCollection.toArray()));
20084560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            }
20091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final List<String> sortNames = VCardUtils.constructListFromValue(sortAsCollection
20101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .iterator().next(), mVCardType);
20114560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            int size = sortNames.size();
20124560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            if (size > 3) {
20134560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa                size = 3;
20144560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            }
20154560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            switch (size) {
20161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            case 3:
20171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mNameData.mPhoneticMiddle = sortNames.get(2); //$FALL-THROUGH$
20181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            case 2:
20191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mNameData.mPhoneticGiven = sortNames.get(1); //$FALL-THROUGH$
20201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            default:
20211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mNameData.mPhoneticFamily = sortNames.get(0);
20221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                break;
20234560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            }
20244560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        }
20254560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa    }
20264560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa
20274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    @SuppressWarnings("fallthrough")
20284560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa    private void handleNProperty(final List<String> paramValues,
20294560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            Map<String, Collection<String>> paramMap) {
20304560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        // in vCard 4.0, SORT-AS parameter is available.
20314560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        tryHandleSortAsName(paramMap);
20324560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa
20334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // Family, Given, Middle, Prefix, Suffix. (1 - 5)
20344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        int size;
20354560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        if (paramValues == null || (size = paramValues.size()) < 1) {
20364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return;
20374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
20384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (size > 5) {
20394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            size = 5;
20404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
20414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
20424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        switch (size) {
20434560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        // Fall-through.
20441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 5:
20451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mSuffix = paramValues.get(4);
20461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 4:
20471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mPrefix = paramValues.get(3);
20481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 3:
20491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mMiddle = paramValues.get(2);
20501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 2:
20511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mGiven = paramValues.get(1);
20521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        default:
20531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mFamily = paramValues.get(0);
20544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
20554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
20564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
20574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
20581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * Note: Some Japanese mobile phones use this field for phonetic name, since
20591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * vCard 2.1 does not have "SORT-STRING" type. Also, in some cases, the
20601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * field has some ';'s in it. Assume the ';' means the same meaning in N
20611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * property
20624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
20634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    @SuppressWarnings("fallthrough")
20644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void handlePhoneticNameFromSound(List<String> elems) {
20651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (!(TextUtils.isEmpty(mNameData.mPhoneticFamily)
20661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                && TextUtils.isEmpty(mNameData.mPhoneticMiddle) && TextUtils
20671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                .isEmpty(mNameData.mPhoneticGiven))) {
20684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // This means the other properties like "X-PHONETIC-FIRST-NAME" was already found.
20694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // Ignore "SOUND;X-IRMC-N".
20704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return;
20714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
20724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
20734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        int size;
20744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (elems == null || (size = elems.size()) < 1) {
20754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return;
20764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
20774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
20784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // Assume that the order is "Family, Given, Middle".
20791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // This is not from specification but mere assumption. Some Japanese
20801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // phones use this order.
20814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (size > 3) {
20824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            size = 3;
20834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
20844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
20854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (elems.get(0).length() > 0) {
20864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            boolean onlyFirstElemIsNonEmpty = true;
20874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            for (int i = 1; i < size; i++) {
20884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (elems.get(i).length() > 0) {
20894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    onlyFirstElemIsNonEmpty = false;
20904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    break;
20914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
20924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
20934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (onlyFirstElemIsNonEmpty) {
20944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                final String[] namesArray = elems.get(0).split(" ");
20954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                final int nameArrayLength = namesArray.length;
20964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (nameArrayLength == 3) {
20974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    // Assume the string is "Family Middle Given".
20981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mPhoneticFamily = namesArray[0];
20991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mPhoneticMiddle = namesArray[1];
21001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mPhoneticGiven = namesArray[2];
21014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                } else if (nameArrayLength == 2) {
21024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    // Assume the string is "Family Given" based on the Japanese mobile
21034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    // phones' preference.
21041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mPhoneticFamily = namesArray[0];
21051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mPhoneticGiven = namesArray[1];
21064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                } else {
21071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mPhoneticGiven = elems.get(0);
21084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
21094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return;
21104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
21114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
21124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
21134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        switch (size) {
21141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // fallthrough
21151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 3:
21161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mPhoneticMiddle = elems.get(2);
21171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 2:
21181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mPhoneticGiven = elems.get(1);
21191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        default:
21201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mPhoneticFamily = elems.get(0);
21214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
21224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
21234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
21241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void addProperty(final VCardProperty property) {
21251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        final String propertyName = property.getName();
21261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        final Map<String, Collection<String>> paramMap = property.getParameterMap();
21271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        final List<String> propertyValueList = property.getValueList();
21281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        byte[] propertyBytes = property.getByteValue();
21294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
21301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if ((propertyValueList == null || propertyValueList.size() == 0)
21311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                && propertyBytes == null) {
21324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return;
21334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
21341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        final String propValue = (propertyValueList != null
21351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                ? listToString(propertyValueList).trim()
21361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                : null);
21374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
21381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (propertyName.equals(VCardConstants.PROPERTY_VERSION)) {
21394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // vCard version. Ignore this.
21401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_FN)) {
21411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mFormatted = propValue;
21421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_NAME)) {
21431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // Only in vCard 3.0. Use this if FN doesn't exist though it is
21441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // required in vCard 3.0.
21451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (TextUtils.isEmpty(mNameData.mFormatted)) {
21461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mNameData.mFormatted = propValue;
21471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
21481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_N)) {
21491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            handleNProperty(propertyValueList, paramMap);
21501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_SORT_STRING)) {
2151517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            mNameData.mSortString = propValue;
21521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_NICKNAME)
21531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                || propertyName.equals(VCardConstants.ImportOnly.PROPERTY_X_NICKNAME)) {
21544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            addNickName(propValue);
21551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_SOUND)) {
21564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
21574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (typeCollection != null
21584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    && typeCollection.contains(VCardConstants.PARAM_TYPE_X_IRMC_N)) {
21594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // As of 2009-10-08, Parser side does not split a property value into separated
21604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // values using ';' (in other words, propValueList.size() == 1),
21614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // which is correct behavior from the view of vCard 2.1.
21624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // But we want it to be separated, so do the separation here.
21631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final List<String> phoneticNameList = VCardUtils.constructListFromValue(propValue,
21641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        mVCardType);
21654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                handlePhoneticNameFromSound(phoneticNameList);
21664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
21674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // Ignore this field since Android cannot understand what it is.
21684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
21691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_ADR)) {
21704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            boolean valuesAreAllEmpty = true;
21711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            for (String value : propertyValueList) {
21721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (!TextUtils.isEmpty(value)) {
21734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    valuesAreAllEmpty = false;
21744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    break;
21754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
21764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
21774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (valuesAreAllEmpty) {
21784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return;
21794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
21804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
21814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            int type = -1;
21821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            String label = null;
21834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            boolean isPrimary = false;
218400b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa            final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
21854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (typeCollection != null) {
218600b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                for (final String typeStringOrg : typeCollection) {
218700b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    final String typeStringUpperCase = typeStringOrg.toUpperCase();
218800b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_PREF)) {
21894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        isPrimary = true;
219000b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_HOME)) {
21914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        type = StructuredPostal.TYPE_HOME;
21921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        label = null;
21931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_WORK)
21941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                            || typeStringUpperCase
21951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                                    .equalsIgnoreCase(VCardConstants.PARAM_EXTRA_TYPE_COMPANY)) {
21964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        // "COMPANY" seems emitted by Windows Mobile, which is not
21974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        // specifically supported by vCard 2.1. We assume this is same
21984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        // as "WORK".
21994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        type = StructuredPostal.TYPE_WORK;
22001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        label = null;
22011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_ADR_TYPE_PARCEL)
22021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                            || typeStringUpperCase.equals(VCardConstants.PARAM_ADR_TYPE_DOM)
22031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                            || typeStringUpperCase.equals(VCardConstants.PARAM_ADR_TYPE_INTL)) {
22044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        // We do not have any appropriate way to store this information.
22051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    } else if (type < 0) { // If no other type is specified before.
22064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        type = StructuredPostal.TYPE_CUSTOM;
22071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        if (typeStringUpperCase.startsWith("X-")) { // If X- or x-
220800b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                            label = typeStringOrg.substring(2);
220900b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                        } else {
221000b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                            label = typeStringOrg;
221100b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                        }
22124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
22134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
22144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
22154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // We use "HOME" as default
22164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (type < 0) {
22174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                type = StructuredPostal.TYPE_HOME;
22184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
22194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
22201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            addPostal(type, propertyValueList, label, isPrimary);
22211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_EMAIL)) {
22224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            int type = -1;
22234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            String label = null;
22244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            boolean isPrimary = false;
222500b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa            final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
22264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (typeCollection != null) {
222700b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                for (final String typeStringOrg : typeCollection) {
222800b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    final String typeStringUpperCase = typeStringOrg.toUpperCase();
222900b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_PREF)) {
22304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        isPrimary = true;
223100b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_HOME)) {
22324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        type = Email.TYPE_HOME;
223300b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_WORK)) {
22344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        type = Email.TYPE_WORK;
223500b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_CELL)) {
22364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        type = Email.TYPE_MOBILE;
22371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    } else if (type < 0) { // If no other type is specified before
22381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        if (typeStringUpperCase.startsWith("X-")) { // If X- or x-
223900b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                            label = typeStringOrg.substring(2);
224000b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                        } else {
224100b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                            label = typeStringOrg;
22424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        }
22434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        type = Email.TYPE_CUSTOM;
22444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
22454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
22464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
22474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (type < 0) {
22484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                type = Email.TYPE_OTHER;
22494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
22504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            addEmail(type, propValue, label, isPrimary);
22511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_ORG)) {
22524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // vCard specification does not specify other types.
22534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final int type = Organization.TYPE_WORK;
22544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            boolean isPrimary = false;
22554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
22564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (typeCollection != null) {
22574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                for (String typeString : typeCollection) {
22584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) {
22594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        isPrimary = true;
22604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
22614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
22624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
22631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            handleOrgValue(type, propertyValueList, paramMap, isPrimary);
22641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_TITLE)) {
22654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            handleTitleValue(propValue);
22661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_ROLE)) {
22674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // This conflicts with TITLE. Ignore for now...
22684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // handleTitleValue(propValue);
22691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_PHOTO)
22701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                || propertyName.equals(VCardConstants.PROPERTY_LOGO)) {
22714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            Collection<String> paramMapValue = paramMap.get("VALUE");
22724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (paramMapValue != null && paramMapValue.contains("URL")) {
22734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // Currently we do not have appropriate example for testing this case.
22744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
22754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                final Collection<String> typeCollection = paramMap.get("TYPE");
22764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                String formatName = null;
22774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                boolean isPrimary = false;
22784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (typeCollection != null) {
22794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    for (String typeValue : typeCollection) {
22804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        if (VCardConstants.PARAM_TYPE_PREF.equals(typeValue)) {
22814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            isPrimary = true;
22821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        } else if (formatName == null) {
22834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            formatName = typeValue;
22844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        }
22854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
22864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
22871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                addPhotoBytes(formatName, propertyBytes, isPrimary);
22884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
22891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_TEL)) {
22901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            String phoneNumber = null;
22911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            boolean isSip = false;
229237634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa            if (VCardConfig.isVersion40(mVCardType)) {
229337634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                // Given propValue is in URI format, not in phone number format used until
229437634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                // vCard 3.0.
22951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (propValue.startsWith("sip:")) {
22961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    isSip = true;
229737634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                } else if (propValue.startsWith("tel:")) {
229837634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                    phoneNumber = propValue.substring(4);
229937634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                } else {
230037634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                    // We don't know appropriate way to handle the other schemas. Also,
230137634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                    // we may still have non-URI phone number. To keep given data as much as
230237634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                    // we can, just save original value here.
230337634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                    phoneNumber = propValue;
230437634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                }
230537634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa            } else {
230637634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                phoneNumber = propValue;
230737634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa            }
230837634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa
23091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (isSip) {
23101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
23111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                handleSipCase(propValue, typeCollection);
23124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
23131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (propValue.length() == 0) {
23141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    return;
23151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
23164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
23171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
23181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final Object typeObject = VCardUtils.getPhoneTypeFromStrings(typeCollection,
23191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        phoneNumber);
23201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final int type;
23211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final String label;
23221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (typeObject instanceof Integer) {
23231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    type = (Integer) typeObject;
23241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    label = null;
23251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                } else {
23261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    type = Phone.TYPE_CUSTOM;
23271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    label = typeObject.toString();
23281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
23291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
23301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final boolean isPrimary;
23311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (typeCollection != null &&
23321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        typeCollection.contains(VCardConstants.PARAM_TYPE_PREF)) {
23331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    isPrimary = true;
23341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                } else {
23351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    isPrimary = false;
23361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
23371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
23381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                addPhone(type, phoneNumber, label, isPrimary);
23394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
23401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_X_SKYPE_PSTNNUMBER)) {
23414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // The phone number available via Skype.
23424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
23434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final int type = Phone.TYPE_OTHER;
23444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final boolean isPrimary;
23451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (typeCollection != null
23461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && typeCollection.contains(VCardConstants.PARAM_TYPE_PREF)) {
23474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                isPrimary = true;
23484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
23494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                isPrimary = false;
23504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
23514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            addPhone(type, propValue, null, isPrimary);
23521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (sImMap.containsKey(propertyName)) {
23531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final int protocol = sImMap.get(propertyName);
23544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            boolean isPrimary = false;
23554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            int type = -1;
23564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
23574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (typeCollection != null) {
23584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                for (String typeString : typeCollection) {
23594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) {
23604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        isPrimary = true;
23614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    } else if (type < 0) {
23624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        if (typeString.equalsIgnoreCase(VCardConstants.PARAM_TYPE_HOME)) {
23634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            type = Im.TYPE_HOME;
23644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        } else if (typeString.equalsIgnoreCase(VCardConstants.PARAM_TYPE_WORK)) {
23654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            type = Im.TYPE_WORK;
23664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        }
23674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
23684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
23694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
23704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (type < 0) {
237106ae82316d0b5f7222a7a1d15b7d03df88fdea15Daisuke Miyakawa                type = Im.TYPE_HOME;
23724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
23731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            addIm(protocol, null, propValue, type, isPrimary);
23741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_NOTE)) {
23754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            addNote(propValue);
23761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_URL)) {
23774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (mWebsiteList == null) {
23781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mWebsiteList = new ArrayList<WebsiteData>(1);
23791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
23801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mWebsiteList.add(new WebsiteData(propValue));
23811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_BDAY)) {
23821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBirthday = new BirthdayData(propValue);
23831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_ANNIVERSARY)) {
23841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mAnniversary = new AnniversaryData(propValue);
23851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_X_PHONETIC_FIRST_NAME)) {
23861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mPhoneticGiven = propValue;
23871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_X_PHONETIC_MIDDLE_NAME)) {
23881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mPhoneticMiddle = propValue;
23891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_X_PHONETIC_LAST_NAME)) {
23901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mPhoneticFamily = propValue;
23911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_IMPP)) {
239288d0f1ef715f2e1209eba5d175b1b71c556fa8b0Daisuke Miyakawa            // See also RFC 4770 (for vCard 3.0)
23931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (propValue.startsWith("sip:")) {
23941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
23951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                handleSipCase(propValue, typeCollection);
239688d0f1ef715f2e1209eba5d175b1b71c556fa8b0Daisuke Miyakawa            }
23971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_X_SIP)) {
23985db8b7baeffb35191032789cb0b0d643b78f0120Daisuke Miyakawa            if (!TextUtils.isEmpty(propValue)) {
23991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
24001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                handleSipCase(propValue, typeCollection);
24011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
24021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_X_ANDROID_CUSTOM)) {
24031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final List<String> customPropertyList = VCardUtils.constructListFromValue(propValue,
24041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mVCardType);
24051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            handleAndroidCustomProperty(customPropertyList);
24061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else {
24071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
24081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // Be careful when adding some logic here, as some blocks above may use "return".
24091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
24100fc278de46840f89c01aa984de7565c1f97e3103Daisuke Miyakawa
24111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    /**
24121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * @param propValue may contain "sip:" at the beginning.
24131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * @param typeCollection
24141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     */
24151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private void handleSipCase(String propValue, Collection<String> typeCollection) {
24161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (TextUtils.isEmpty(propValue)) {
24171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return;
24181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
24191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (propValue.startsWith("sip:")) {
24201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            propValue = propValue.substring(4);
24211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (propValue.length() == 0) {
24221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return;
24231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
24241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
24251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
24261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        int type = -1;
24271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        String label = null;
24281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        boolean isPrimary = false;
24291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (typeCollection != null) {
24301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            for (final String typeStringOrg : typeCollection) {
24311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final String typeStringUpperCase = typeStringOrg.toUpperCase();
24321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_PREF)) {
24331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    isPrimary = true;
24341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_HOME)) {
24351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    type = SipAddress.TYPE_HOME;
24361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_WORK)) {
24371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    type = SipAddress.TYPE_WORK;
24381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                } else if (type < 0) { // If no other type is specified before
24391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    if (typeStringUpperCase.startsWith("X-")) { // If X- or x-
24401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        label = typeStringOrg.substring(2);
244137634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                    } else {
24421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        label = typeStringOrg;
244337634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                    }
24441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    type = SipAddress.TYPE_CUSTOM;
24450fc278de46840f89c01aa984de7565c1f97e3103Daisuke Miyakawa                }
24465db8b7baeffb35191032789cb0b0d643b78f0120Daisuke Miyakawa            }
24474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
24481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (type < 0) {
24491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            type = SipAddress.TYPE_OTHER;
24501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
24511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        addSip(propValue, type, label, isPrimary);
24524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
24534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
245448dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    public void addChild(VCardEntry child) {
245548dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        if (mChildren == null) {
245648dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa            mChildren = new ArrayList<VCardEntry>();
245748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        }
245848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        mChildren.add(child);
245948dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    }
246048dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
24614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void handleAndroidCustomProperty(final List<String> customPropertyList) {
24621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mAndroidCustomDataList == null) {
24631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mAndroidCustomDataList = new ArrayList<AndroidCustomData>();
24644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
24651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mAndroidCustomDataList
24661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                .add(AndroidCustomData.constructAndroidCustomData(customPropertyList));
24674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
24684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
24694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
24704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * Construct the display name. The constructed data must not be null.
24714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
24721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private String constructDisplayName() {
24731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        String displayName = null;
24744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // FullName (created via "FN" or "NAME" field) is prefered.
24751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (!TextUtils.isEmpty(mNameData.mFormatted)) {
24761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = mNameData.mFormatted;
24771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (!mNameData.emptyStructuredName()) {
24781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = VCardUtils.constructNameFromElements(mVCardType, mNameData.mFamily,
24791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mMiddle, mNameData.mGiven, mNameData.mPrefix, mNameData.mSuffix);
24801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (!mNameData.emptyPhoneticStructuredName()) {
24811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = VCardUtils.constructNameFromElements(mVCardType,
24821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mPhoneticFamily, mNameData.mPhoneticMiddle, mNameData.mPhoneticGiven);
24834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (mEmailList != null && mEmailList.size() > 0) {
24841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = mEmailList.get(0).mAddress;
24854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (mPhoneList != null && mPhoneList.size() > 0) {
24861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = mPhoneList.get(0).mNumber;
24874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (mPostalList != null && mPostalList.size() > 0) {
24881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = mPostalList.get(0).getFormattedAddress(mVCardType);
24894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (mOrganizationList != null && mOrganizationList.size() > 0) {
24901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = mOrganizationList.get(0).getFormattedString();
24914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
24921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (displayName == null) {
24931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = "";
24944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
24951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return displayName;
24964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
24974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
24984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
24994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * Consolidate several fielsds (like mName) using name candidates,
25004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
25014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void consolidateFields() {
25021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mNameData.displayName = constructDisplayName();
250348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    }
250448dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
25051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    /**
25061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * @return true when this object has nothing meaningful for Android's
25071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *         Contacts, and thus is "ignorable" for Android's Contacts. This
25081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *         does not mean an original vCard is really empty. Even when the
25091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *         original vCard has some fields, this may ignore it if those
25101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *         fields cannot be transcoded into Android's Contacts
25111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *         representation.
25121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     */
25131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public boolean isIgnorable() {
25141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        IsIgnorableIterator iterator = new IsIgnorableIterator();
25151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateAllData(iterator);
25161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return iterator.getResult();
251748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    }
251848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
2519f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa    /**
25201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * Constructs the list of insert operation for this object. When the
25211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * operationList argument is null, this method creates a new ArrayList and
25221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * return it. The returned object is filled with new insert operations for
25231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * this object. When operationList argument is not null, this method appends
25241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * those new operations into the object instead of creating a new ArrayList.
2525f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa     *
2526f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa     * @param resolver {@link ContentResolver} object to be used in this method.
25271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * @param operationList object to be filled. You can use this argument to
25281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *            concatinate operation lists. If null, this method creates a
25291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *            new array object.
25301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * @return If operationList argument is null, new object with new insert
25311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *         operations. If it is not null, the operationList object with
25321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *         operations inserted by this method.
2533f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa     */
25341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public ArrayList<ContentProviderOperation> constructInsertOperations(ContentResolver resolver,
25351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            ArrayList<ContentProviderOperation> operationList) {
2536f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        if (operationList == null) {
2537f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            operationList = new ArrayList<ContentProviderOperation>();
2538f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        }
2539f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa
25401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (isIgnorable()) {
254148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa            return operationList;
254248dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        }
254348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
2544f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        final int backReferenceIndex = operationList.size();
2545f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa
25464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // After applying the batch the first result's Uri is returned so it is important that
2547f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        // the RawContact is the first operation that gets inserted into the list.
25481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        ContentProviderOperation.Builder builder = ContentProviderOperation
25491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                .newInsert(RawContacts.CONTENT_URI);
25504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mAccount != null) {
25514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.withValue(RawContacts.ACCOUNT_NAME, mAccount.name);
25524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.withValue(RawContacts.ACCOUNT_TYPE, mAccount.type);
25534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
25544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.withValue(RawContacts.ACCOUNT_NAME, null);
25554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.withValue(RawContacts.ACCOUNT_TYPE, null);
25564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
25574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        operationList.add(builder.build());
25584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
25591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        int start = operationList.size();
25601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateAllData(new InsertOperationConstrutor(operationList, backReferenceIndex));
25611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        int end = operationList.size();
25624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
2563f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        return operationList;
25644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
25654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
25664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public static VCardEntry buildFromResolver(ContentResolver resolver) {
25674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return buildFromResolver(resolver, Contacts.CONTENT_URI);
25684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
25694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
25704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public static VCardEntry buildFromResolver(ContentResolver resolver, Uri uri) {
25714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return null;
25724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
25734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
25741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private String listToString(List<String> list) {
25754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        final int size = list.size();
25764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (size > 1) {
25774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            StringBuilder builder = new StringBuilder();
25784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            int i = 0;
25794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            for (String type : list) {
25804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                builder.append(type);
25814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (i < size - 1) {
25824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    builder.append(";");
25834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
25844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
25854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return builder.toString();
25864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (size == 1) {
25874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return list.get(0);
25884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
25894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return "";
25904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
25914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
25924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
25931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public final NameData getNameData() {
25941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mNameData;
25954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
25964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
25971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public final List<NicknameData> getNickNameList() {
25981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mNicknameList;
25994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public final String getBirthday() {
26021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mBirthday != null ? mBirthday.mBirthday : null;
26034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public final List<NoteData> getNotes() {
26064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mNoteList;
26074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public final List<PhoneData> getPhoneList() {
26104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mPhoneList;
26114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public final List<EmailData> getEmailList() {
26144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mEmailList;
26154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public final List<PostalData> getPostalList() {
26184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mPostalList;
26194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public final List<OrganizationData> getOrganizationList() {
26224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mOrganizationList;
26234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public final List<ImData> getImList() {
26264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mImList;
26274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public final List<PhotoData> getPhotoList() {
26304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mPhotoList;
26314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public final List<WebsiteData> getWebsiteList() {
26344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mWebsiteList;
26354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
263748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    /**
263848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa     * @hide this interface may be changed for better support of vCard 4.0 (UID)
263948dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa     */
264048dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    public final List<VCardEntry> getChildlen() {
264148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        return mChildren;
264248dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    }
264348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
26444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public String getDisplayName() {
26451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mNameData.displayName == null) {
26461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.displayName = constructDisplayName();
26474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
26481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mNameData.displayName;
26494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa}
2651