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;
45600d08e46f52d510598ffe382bf83f576f7ab8a6Rakesh Iyerimport android.util.Pair;
464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.ArrayList;
484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Arrays;
494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Collection;
504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Collections;
514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.HashMap;
524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.List;
534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Map;
544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/**
561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * Represents one vCard entry, which should start with "BEGIN:VCARD" and end
571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * with "END:VCARD". This class is for bridging between real vCard data and
581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * Android's {@link ContactsContract}, which means some aspects of vCard are
591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * dropped before this object being constructed. Raw vCard data should be first
601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * supplied with {@link #addProperty(VCardProperty)}. After supplying all data,
611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * user should call {@link #consolidateFields()} to prepare some additional
621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * information which is constructable from supplied raw data. TODO: preserve raw
631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * data using {@link VCardProperty}. If it may just waste memory, this at least
641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * should contain them when it cannot convert vCard as a string to Android's
651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * Contacts representation. Those raw properties should _not_ be used for
661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * {@link #isIgnorable()}.
674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */
684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapublic class VCardEntry {
6902117b3d19787ff65486b9f9db8abd338ae4c9f9Daisuke Miyakawa    private static final String LOG_TAG = VCardConstants.LOG_TAG;
704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
7148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    private static final int DEFAULT_ORGANIZATION_TYPE = Organization.TYPE_WORK;
724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private static final Map<String, Integer> sImMap = new HashMap<String, Integer>();
744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    static {
764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.PROPERTY_X_AIM, Im.PROTOCOL_AIM);
774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.PROPERTY_X_MSN, Im.PROTOCOL_MSN);
784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.PROPERTY_X_YAHOO, Im.PROTOCOL_YAHOO);
794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.PROPERTY_X_ICQ, Im.PROTOCOL_ICQ);
804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.PROPERTY_X_JABBER, Im.PROTOCOL_JABBER);
814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.PROPERTY_X_SKYPE_USERNAME, Im.PROTOCOL_SKYPE);
824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.PROPERTY_X_GOOGLE_TALK, Im.PROTOCOL_GOOGLE_TALK);
834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        sImMap.put(VCardConstants.ImportOnly.PROPERTY_X_GOOGLE_TALK_WITH_SPACE,
844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                Im.PROTOCOL_GOOGLE_TALK);
854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public enum EntryLabel {
881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        NAME,
891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        PHONE,
901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        EMAIL,
911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        POSTAL_ADDRESS,
921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        ORGANIZATION,
931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        IM,
941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        PHOTO,
951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        WEBSITE,
961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        SIP,
971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        NICKNAME,
981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        NOTE,
991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        BIRTHDAY,
1001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        ANNIVERSARY,
1011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        ANDROID_CUSTOM
1021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static interface EntryElement {
1051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // Also need to inherit toString(), equals().
1061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel();
1071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
1091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex);
1101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty();
1121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    // TODO: vCard 4.0 logically has multiple formatted names and we need to
1151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    // select the most preferable one using PREF parameter.
1161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    //
1171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    // e.g. (based on rev.13)
1181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    // FN;PREF=1:John M. Doe
1191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    // FN;PREF=2:John Doe
1201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    // FN;PREF=3;John
1211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class NameData implements EntryElement {
1221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mFamily;
1231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mGiven;
1241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mMiddle;
1251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mPrefix;
1261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mSuffix;
1271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // Used only when no family nor given name is found.
1291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mFormatted;
1301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mPhoneticFamily;
1321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mPhoneticGiven;
1331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mPhoneticMiddle;
1341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // For "SORT-STRING" in vCard 3.0.
136517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        private String mSortString;
1371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
1391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * Not in vCard but for {@link StructuredName#DISPLAY_NAME}. This field
1401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * is constructed by VCardEntry on demand. Consider using
1411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * {@link VCardEntry#getDisplayName()}.
1421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
1431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // This field should reflect the other Elem fields like Email,
1441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // PostalAddress, etc., while
1451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // This is static class which cannot see other data. Thus we ask
1461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // VCardEntry to populate it.
1471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String displayName;
1481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean emptyStructuredName() {
1501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mFamily) && TextUtils.isEmpty(mGiven)
1511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.isEmpty(mMiddle) && TextUtils.isEmpty(mPrefix)
1521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.isEmpty(mSuffix);
1531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
1541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean emptyPhoneticStructuredName() {
1561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mPhoneticFamily) && TextUtils.isEmpty(mPhoneticGiven)
1571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.isEmpty(mPhoneticMiddle);
1581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
1591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
1621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
1631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
1641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
1651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(StructuredName.RAW_CONTACT_ID, backReferenceIndex);
1661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
1671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mGiven)) {
1691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.GIVEN_NAME, mGiven);
1701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mFamily)) {
1721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.FAMILY_NAME, mFamily);
1731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mMiddle)) {
1751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.MIDDLE_NAME, mMiddle);
1761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mPrefix)) {
1781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.PREFIX, mPrefix);
1791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mSuffix)) {
1811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.SUFFIX, mSuffix);
1821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            boolean phoneticNameSpecified = false;
1851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mPhoneticGiven)) {
1871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.PHONETIC_GIVEN_NAME, mPhoneticGiven);
1881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                phoneticNameSpecified = true;
1891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mPhoneticFamily)) {
1911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.PHONETIC_FAMILY_NAME, mPhoneticFamily);
1921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                phoneticNameSpecified = true;
1931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mPhoneticMiddle)) {
1951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredName.PHONETIC_MIDDLE_NAME, mPhoneticMiddle);
1961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                phoneticNameSpecified = true;
1971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // SORT-STRING is used only when phonetic names aren't specified in
2001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // the original vCard.
2011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!phoneticNameSpecified) {
202517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                builder.withValue(StructuredName.PHONETIC_GIVEN_NAME, mSortString);
2031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
2041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredName.DISPLAY_NAME, displayName);
2061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
2071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
2101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
2111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return (TextUtils.isEmpty(mFamily) && TextUtils.isEmpty(mMiddle)
2121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.isEmpty(mGiven) && TextUtils.isEmpty(mPrefix)
2131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.isEmpty(mSuffix) && TextUtils.isEmpty(mFormatted)
2141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.isEmpty(mPhoneticFamily) && TextUtils.isEmpty(mPhoneticMiddle)
215517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.isEmpty(mPhoneticGiven) && TextUtils.isEmpty(mSortString));
2161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
2191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
2201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
2211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
2221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
2231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof NameData)) {
2241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
2251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
2261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            NameData nameData = (NameData) obj;
2271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return (TextUtils.equals(mFamily, nameData.mFamily)
2291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mMiddle, nameData.mMiddle)
2301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mGiven, nameData.mGiven)
2311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mPrefix, nameData.mPrefix)
2321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mSuffix, nameData.mSuffix)
2331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mFormatted, nameData.mFormatted)
2341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mPhoneticFamily, nameData.mPhoneticFamily)
2351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mPhoneticMiddle, nameData.mPhoneticMiddle)
236517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.equals(mPhoneticGiven, nameData.mPhoneticGiven)
237517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.equals(mSortString, nameData.mSortString));
238517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
239517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
240517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
241517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
242517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            final String[] hashTargets = new String[] {mFamily, mMiddle, mGiven, mPrefix, mSuffix,
243517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    mFormatted, mPhoneticFamily, mPhoneticMiddle,
244517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    mPhoneticGiven, mSortString};
245517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = 0;
246517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            for (String hashTarget : hashTargets) {
247517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                hash = hash * 31 + (hashTarget != null ? hashTarget.hashCode() : 0);
248517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            }
249517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
2501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
2531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
2541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return String.format("family: %s, given: %s, middle: %s, prefix: %s, suffix: %s",
2551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mFamily, mGiven, mMiddle, mPrefix, mSuffix);
2561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
2591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final EntryLabel getEntryLabel() {
2601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.NAME;
2611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getFamily() {
2641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mFamily;
2651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getMiddle() {
2681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mMiddle;
2691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getGiven() {
2721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mGiven;
2731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getPrefix() {
2761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mPrefix;
2771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getSuffix() {
2801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mSuffix;
2811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
2831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getFormatted() {
2841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mFormatted;
2851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
2861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
287517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public String getSortString() {
288517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return mSortString;
289517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
290517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
2911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /** @hide Just for testing. */
2921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void setFamily(String family) { mFamily = family; }
2931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /** @hide Just for testing. */
2941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void setMiddle(String middle) { mMiddle = middle; }
2951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /** @hide Just for testing. */
2961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void setGiven(String given) { mGiven = given; }
2971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /** @hide Just for testing. */
2981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void setPrefix(String prefix) { mPrefix = prefix; }
2991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /** @hide Just for testing. */
3001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void setSuffix(String suffix) { mSuffix = suffix; }
3011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
3021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class PhoneData implements EntryElement {
3041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mNumber;
3051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mType;
3061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mLabel;
3071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // isPrimary is (not final but) changable, only when there's no
3091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // appropriate one existing
3104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // in the original VCard.
3111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private boolean mIsPrimary;
3121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public PhoneData(String data, int type, String label, boolean isPrimary) {
3141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNumber = data;
3151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mType = type;
3161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mLabel = label;
3171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mIsPrimary = isPrimary;
3181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
3191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
3211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
3221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
3231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
3241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
3251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Phone.RAW_CONTACT_ID, backReferenceIndex);
3261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
3271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Phone.TYPE, mType);
3291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mType == Phone.TYPE_CUSTOM) {
3301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Phone.LABEL, mLabel);
3311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
3321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Phone.NUMBER, mNumber);
3331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mIsPrimary) {
3341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Phone.IS_PRIMARY, 1);
3351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
3361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
3371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
3381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
3401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
3411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mNumber);
3424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
3434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
3444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
3454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public boolean equals(Object obj) {
3461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
3471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
3481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
3494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (!(obj instanceof PhoneData)) {
3504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return false;
3514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
3521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            PhoneData phoneData = (PhoneData) obj;
3531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return (mType == phoneData.mType
3541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mNumber, phoneData.mNumber)
3551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mLabel, phoneData.mLabel)
3561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && (mIsPrimary == phoneData.mIsPrimary));
3574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
3584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
3594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
360517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
361517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mType;
362517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mNumber != null ? mNumber.hashCode() : 0);
363517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mLabel != null ? mLabel.hashCode() : 0);
364517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
365517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
366517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
367517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
368517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
3694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public String toString() {
3701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return String.format("type: %d, data: %s, label: %s, isPrimary: %s", mType, mNumber,
3711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mLabel, mIsPrimary);
3721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
3731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
3751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final EntryLabel getEntryLabel() {
3761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.PHONE;
3771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
3781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getNumber() {
3801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mNumber;
3811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
3821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public int getType() {
3841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mType;
3851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
3861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getLabel() {
3881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mLabel;
3891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
3901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
3911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isPrimary() {
3921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mIsPrimary;
3934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
3944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
3954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
3961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class EmailData implements EntryElement {
3971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mAddress;
3981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mType;
3994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // Used only when TYPE is TYPE_CUSTOM.
4001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mLabel;
4011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final boolean mIsPrimary;
4021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EmailData(String data, int type, String label, boolean isPrimary) {
4041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mType = type;
4051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mAddress = data;
4061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mLabel = label;
4071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mIsPrimary = isPrimary;
4081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
4091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
4111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
4121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
4131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
4141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
4151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Email.RAW_CONTACT_ID, backReferenceIndex);
4161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
4171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Email.TYPE, mType);
4191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mType == Email.TYPE_CUSTOM) {
4201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Email.LABEL, mLabel);
4211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
4221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Email.DATA, mAddress);
4231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mIsPrimary) {
4241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Data.IS_PRIMARY, 1);
4251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
4261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
4271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
4281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
4301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
4311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mAddress);
4324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
4334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
4344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
4354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public boolean equals(Object obj) {
4361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
4371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
4381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
4394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (!(obj instanceof EmailData)) {
4404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return false;
4414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
4421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            EmailData emailData = (EmailData) obj;
4431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return (mType == emailData.mType
4441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mAddress, emailData.mAddress)
4451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mLabel, emailData.mLabel)
4461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && (mIsPrimary == emailData.mIsPrimary));
4474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
4484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
4494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
450517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
451517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mType;
452517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mAddress != null ? mAddress.hashCode() : 0);
453517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mLabel != null ? mLabel.hashCode() : 0);
454517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
455517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
456517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
457517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
458517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
4594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public String toString() {
4601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return String.format("type: %d, data: %s, label: %s, isPrimary: %s", mType, mAddress,
4611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mLabel, mIsPrimary);
4621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
4631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
4651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final EntryLabel getEntryLabel() {
4661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.EMAIL;
4671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
4681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getAddress() {
4701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mAddress;
4711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
4721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public int getType() {
4741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mType;
4751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
4761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getLabel() {
4781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mLabel;
4791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
4801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
4811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isPrimary() {
4821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mIsPrimary;
4834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
4844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
4854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
4861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class PostalData implements EntryElement {
4874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // Determined by vCard specification.
4884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // - PO Box, Extended Addr, Street, Locality, Region, Postal Code, Country Name
4891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private static final int ADDR_MAX_DATA_SIZE = 7;
4901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mPobox;
4911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mExtendedAddress;
4921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mStreet;
4931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mLocalty;
4941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mRegion;
4951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mPostalCode;
4961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mCountry;
4971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mType;
4981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mLabel;
4991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private boolean mIsPrimary;
5001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
5011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /** We keep this for {@link StructuredPostal#FORMATTED_ADDRESS} */
5021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // TODO: need better way to construct formatted address.
5031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private int mVCardType;
5041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
5051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public PostalData(String pobox, String extendedAddress, String street, String localty,
5061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                String region, String postalCode, String country, int type, String label,
5071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                boolean isPrimary, int vcardType) {
5081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mType = type;
5091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mPobox = pobox;
5101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mExtendedAddress = extendedAddress;
5111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mStreet = street;
5121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mLocalty = localty;
5131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mRegion = region;
5141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mPostalCode = postalCode;
5151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mCountry = country;
5161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mLabel = label;
5171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mIsPrimary = isPrimary;
5181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mVCardType = vcardType;
5191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
5201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
5211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
5221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * Accepts raw propertyValueList in vCard and constructs PostalData.
5231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
5241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public static PostalData constructPostalData(final List<String> propValueList,
5251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final int type, final String label, boolean isPrimary, int vcardType) {
5261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final String[] dataArray = new String[ADDR_MAX_DATA_SIZE];
5274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
5284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            int size = propValueList.size();
5294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (size > ADDR_MAX_DATA_SIZE) {
5304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                size = ADDR_MAX_DATA_SIZE;
5314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
5324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
5334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // adr-value = 0*6(text-value ";") text-value
5341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // ; PO Box, Extended Address, Street, Locality, Region, Postal Code, Country Name
5354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            //
5364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // Use Iterator assuming List may be LinkedList, though actually it is
5374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // always ArrayList in the current implementation.
5384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            int i = 0;
5394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            for (String addressElement : propValueList) {
5404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                dataArray[i] = addressElement;
5414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (++i >= size) {
5424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    break;
5434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
5444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
5454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            while (i < ADDR_MAX_DATA_SIZE) {
5464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                dataArray[i++] = null;
5474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
5484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
5491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return new PostalData(dataArray[0], dataArray[1], dataArray[2], dataArray[3],
5501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    dataArray[4], dataArray[5], dataArray[6], type, label, isPrimary, vcardType);
5514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
5524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
5534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
5541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
5551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
5561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
5571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
5581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(StructuredPostal.RAW_CONTACT_ID, backReferenceIndex);
5591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE);
5601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
5611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.TYPE, mType);
5621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mType == StructuredPostal.TYPE_CUSTOM) {
5631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(StructuredPostal.LABEL, mLabel);
5644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
5651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
5661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final String streetString;
5671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (TextUtils.isEmpty(mStreet)) {
5681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (TextUtils.isEmpty(mExtendedAddress)) {
5691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    streetString = null;
5701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                } else {
5711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    streetString = mExtendedAddress;
5721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
5731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            } else {
5741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (TextUtils.isEmpty(mExtendedAddress)) {
5751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    streetString = mStreet;
5761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                } else {
5771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    streetString = mStreet + " " + mExtendedAddress;
5781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
5791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
5801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.POBOX, mPobox);
5811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.STREET, streetString);
5821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.CITY, mLocalty);
5831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.REGION, mRegion);
5841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.POSTCODE, mPostalCode);
5851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.COUNTRY, mCountry);
5861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
5871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(StructuredPostal.FORMATTED_ADDRESS, getFormattedAddress(mVCardType));
5881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mIsPrimary) {
5891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Data.IS_PRIMARY, 1);
5901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
5911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
5924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
5934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
5944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public String getFormattedAddress(final int vcardType) {
5954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            StringBuilder builder = new StringBuilder();
5964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            boolean empty = true;
5971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final String[] dataArray = new String[] {
5981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mPobox, mExtendedAddress, mStreet, mLocalty, mRegion, mPostalCode, mCountry
5991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            };
6004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (VCardConfig.isJapaneseDevice(vcardType)) {
6014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // In Japan, the order is reversed.
6024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                for (int i = ADDR_MAX_DATA_SIZE - 1; i >= 0; i--) {
6034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    String addressPart = dataArray[i];
6044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    if (!TextUtils.isEmpty(addressPart)) {
6054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        if (!empty) {
6064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            builder.append(' ');
6074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        } else {
6084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            empty = false;
6094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        }
6104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        builder.append(addressPart);
6114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
6124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
6134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
6144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                for (int i = 0; i < ADDR_MAX_DATA_SIZE; i++) {
6154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    String addressPart = dataArray[i];
6164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    if (!TextUtils.isEmpty(addressPart)) {
6174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        if (!empty) {
6184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            builder.append(' ');
6194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        } else {
6204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            empty = false;
6214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        }
6224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        builder.append(addressPart);
6234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
6244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
6254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
6264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
6274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return builder.toString().trim();
6284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
6294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
6304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
6311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
632517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return (TextUtils.isEmpty(mPobox)
633517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.isEmpty(mExtendedAddress)
634517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.isEmpty(mStreet)
635517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.isEmpty(mLocalty)
636517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.isEmpty(mRegion)
637517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.isEmpty(mPostalCode)
638517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.isEmpty(mCountry));
6391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
6401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
6411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
6421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
6431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
6441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
6451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
6461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof PostalData)) {
6471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
6481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
6491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final PostalData postalData = (PostalData) obj;
6501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return (mType == postalData.mType)
6511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && (mType == StructuredPostal.TYPE_CUSTOM ? TextUtils.equals(mLabel,
652517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                            postalData.mLabel) : true)
653517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && (mIsPrimary == postalData.mIsPrimary)
6541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mPobox, postalData.mPobox)
6551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mExtendedAddress, postalData.mExtendedAddress)
6561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mStreet, postalData.mStreet)
6571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mLocalty, postalData.mLocalty)
6581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mRegion, postalData.mRegion)
6591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mPostalCode, postalData.mPostalCode)
6601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mCountry, postalData.mCountry);
6611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
6621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
6631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
664517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
665517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mType;
666517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mLabel != null ? mLabel.hashCode() : 0);
667517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
668517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
669517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            final String[] hashTargets = new String[] {mPobox, mExtendedAddress, mStreet,
670517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    mLocalty, mRegion, mPostalCode, mCountry};
671517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            for (String hashTarget : hashTargets) {
672517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                hash = hash * 31 + (hashTarget != null ? hashTarget.hashCode() : 0);
673517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            }
674517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
675517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
676517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
677517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
6784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public String toString() {
6791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return String.format("type: %d, label: %s, isPrimary: %s, pobox: %s, "
6801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    + "extendedAddress: %s, street: %s, localty: %s, region: %s, postalCode %s, "
6811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    + "country: %s", mType, mLabel, mIsPrimary, mPobox, mExtendedAddress, mStreet,
6821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mLocalty, mRegion, mPostalCode, mCountry);
6831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
6841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
6851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
6861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final EntryLabel getEntryLabel() {
6871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.POSTAL_ADDRESS;
6881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
6891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
6901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getPobox() {
6911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mPobox;
6921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
6931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
6941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getExtendedAddress() {
6951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mExtendedAddress;
6961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
6971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
6981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getStreet() {
6991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mStreet;
7001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getLocalty() {
7031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mLocalty;
7041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getRegion() {
7071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mRegion;
7081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getPostalCode() {
7111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mPostalCode;
7121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getCountry() {
7151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mCountry;
7161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public int getType() {
7191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mType;
7201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getLabel() {
7231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mLabel;
7241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isPrimary() {
7271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mIsPrimary;
7284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
7294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
7304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
7311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class OrganizationData implements EntryElement {
7324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // non-final is Intentional: we may change the values since this info is separated into
7331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // two parts in vCard: "ORG" + "TITLE", and we have to cope with each field in different
7341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // timing.
7351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mOrganizationName;
7361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mDepartmentName;
7371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private String mTitle;
7381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mPhoneticName; // We won't have this in "TITLE" property.
7391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mType;
7401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private boolean mIsPrimary;
7411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public OrganizationData(final String organizationName, final String departmentName,
7431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final String titleName, final String phoneticName, int type,
7444560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa                final boolean isPrimary) {
7451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mType = type;
7461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mOrganizationName = organizationName;
7471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mDepartmentName = departmentName;
7481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mTitle = titleName;
7491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mPhoneticName = phoneticName;
7501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mIsPrimary = isPrimary;
7511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getFormattedString() {
7541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final StringBuilder builder = new StringBuilder();
7551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mOrganizationName)) {
7561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.append(mOrganizationName);
7571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mDepartmentName)) {
7601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (builder.length() > 0) {
7611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    builder.append(", ");
7621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
7631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.append(mDepartmentName);
7641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.isEmpty(mTitle)) {
7671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (builder.length() > 0) {
7681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    builder.append(", ");
7691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
7701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.append(mTitle);
7711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return builder.toString();
7741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
7751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
7761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
7771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
7781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
7791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
7801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
7811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Organization.RAW_CONTACT_ID, backReferenceIndex);
7821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
7831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Organization.TYPE, mType);
7841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mOrganizationName != null) {
7851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Organization.COMPANY, mOrganizationName);
7861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mDepartmentName != null) {
7881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Organization.DEPARTMENT, mDepartmentName);
7891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mTitle != null) {
7911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Organization.TITLE, mTitle);
7921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mPhoneticName != null) {
7941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Organization.PHONETIC_NAME, mPhoneticName);
7951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mIsPrimary) {
7971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Organization.IS_PRIMARY, 1);
7981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
7991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
8001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
8031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
8041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mOrganizationName) && TextUtils.isEmpty(mDepartmentName)
8051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mPhoneticName);
8064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
8074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
8084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
8094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        public boolean equals(Object obj) {
8101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
8111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
8121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
8134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (!(obj instanceof OrganizationData)) {
8144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return false;
8154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
8161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            OrganizationData organization = (OrganizationData) obj;
8171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return (mType == organization.mType
8181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mOrganizationName, organization.mOrganizationName)
8191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mDepartmentName, organization.mDepartmentName)
8201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mTitle, organization.mTitle)
8211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && (mIsPrimary == organization.mIsPrimary));
8224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
8234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
8241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
825517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
826517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mType;
827517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mOrganizationName != null ? mOrganizationName.hashCode() : 0);
828517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mDepartmentName != null ? mDepartmentName.hashCode() : 0);
829517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mTitle != null ? mTitle.hashCode() : 0);
830517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
831517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
832517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
833517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
834517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
8351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
8361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return String.format(
8371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    "type: %d, organization: %s, department: %s, title: %s, isPrimary: %s", mType,
8381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mOrganizationName, mDepartmentName, mTitle, mIsPrimary);
8391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
8421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final EntryLabel getEntryLabel() {
8431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.ORGANIZATION;
8441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getOrganizationName() {
8471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mOrganizationName;
8481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getDepartmentName() {
8511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mDepartmentName;
8521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getTitle() {
8551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mTitle;
8561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getPhoneticName() {
8591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mPhoneticName;
8601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public int getType() {
8631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mType;
8641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isPrimary() {
8671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mIsPrimary;
8681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
8701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class ImData implements EntryElement {
8721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mAddress;
8731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mProtocol;
8741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mCustomProtocol;
8751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mType;
8761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final boolean mIsPrimary;
8771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public ImData(final int protocol, final String customProtocol, final String address,
8791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final int type, final boolean isPrimary) {
8801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mProtocol = protocol;
8811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mCustomProtocol = customProtocol;
8821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mType = type;
8831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mAddress = address;
8841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mIsPrimary = isPrimary;
8851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
8861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
8871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
8881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
8891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
8901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
8911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
8921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Im.RAW_CONTACT_ID, backReferenceIndex);
8931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
8941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Im.TYPE, mType);
8951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Im.PROTOCOL, mProtocol);
8961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Im.DATA, mAddress);
8971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mProtocol == Im.PROTOCOL_CUSTOM) {
8981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Im.CUSTOM_PROTOCOL, mCustomProtocol);
8991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
9001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mIsPrimary) {
9011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Data.IS_PRIMARY, 1);
9024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
9031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
9041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
9061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
9071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
9081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mAddress);
9091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
9121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
9131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
9141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
9151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
9161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof ImData)) {
9171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
9181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
9191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            ImData imData = (ImData) obj;
920517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return (mType == imData.mType
921517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && mProtocol == imData.mProtocol
9221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mCustomProtocol, imData.mCustomProtocol)
9231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && TextUtils.equals(mAddress, imData.mAddress)
9241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && (mIsPrimary == imData.mIsPrimary));
9251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
928517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
929517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mType;
930517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + mProtocol;
931517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mCustomProtocol != null ? mCustomProtocol.hashCode() : 0);
932517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mAddress != null ? mAddress.hashCode() : 0);
933517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
934517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
935517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
936517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
937517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
9381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
9391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return String.format(
9401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    "type: %d, protocol: %d, custom_protcol: %s, data: %s, isPrimary: %s", mType,
9411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mProtocol, mCustomProtocol, mAddress, mIsPrimary);
9421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
9451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final EntryLabel getEntryLabel() {
9461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.IM;
9471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getAddress() {
9501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mAddress;
9511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
9541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * One of the value available for {@link Im#PROTOCOL}. e.g.
9551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * {@link Im#PROTOCOL_GOOGLE_TALK}
9561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
9571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public int getProtocol() {
9581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mProtocol;
9591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getCustomProtocol() {
9621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mCustomProtocol;
9631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public int getType() {
9661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mType;
9671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isPrimary() {
9701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mIsPrimary;
9711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
9731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class PhotoData implements EntryElement {
9751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // private static final String FORMAT_FLASH = "SWF";
9761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // used when type is not defined in ContactsContract.
9781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mFormat;
9791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final boolean mIsPrimary;
9801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
98187315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa        private final byte[] mBytes;
9821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
983517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        private Integer mHashCode = null;
984517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
9851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public PhotoData(String format, byte[] photoBytes, boolean isPrimary) {
9861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mFormat = format;
98787315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa            mBytes = photoBytes;
9881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mIsPrimary = isPrimary;
9891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
9901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
9911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
9921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
9931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
9941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
9951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
9961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Photo.RAW_CONTACT_ID, backReferenceIndex);
9971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE);
99887315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa            builder.withValue(Photo.PHOTO, mBytes);
9991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mIsPrimary) {
10001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(Photo.IS_PRIMARY, 1);
10011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
10021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
10031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
10061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
100787315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa            return mBytes == null || mBytes.length == 0;
10081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
10111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
10121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
10131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
10141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
10151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof PhotoData)) {
10161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
10171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
10181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            PhotoData photoData = (PhotoData) obj;
10191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return (TextUtils.equals(mFormat, photoData.mFormat)
102087315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa                    && Arrays.equals(mBytes, photoData.mBytes)
10211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && (mIsPrimary == photoData.mIsPrimary));
10221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1025517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1026517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            if (mHashCode != null) {
1027517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                return mHashCode;
1028517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            }
1029517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1030517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mFormat != null ? mFormat.hashCode() : 0;
1031517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31;
103287315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa            if (mBytes != null) {
103387315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa                for (byte b : mBytes) {
1034517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    hash += b;
1035517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                }
1036517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            }
1037517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1038517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
1039517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            mHashCode = hash;
1040517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
1041517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1042517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1043517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
10441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
104587315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa            return String.format("format: %s: size: %d, isPrimary: %s", mFormat, mBytes.length,
10461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mIsPrimary);
10471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
10501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final EntryLabel getEntryLabel() {
10511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.PHOTO;
10521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getFormat() {
10551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mFormat;
10561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public byte[] getBytes() {
105987315f4cddec4c9bb09a48497c8b6bd65a8b99c7Daisuke Miyakawa            return mBytes;
10601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isPrimary() {
10631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mIsPrimary;
10641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
10661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class NicknameData implements EntryElement {
10681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mNickname;
10691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public NicknameData(String nickname) {
10711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNickname = nickname;
10721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
10751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
10761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
10771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
10781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
10791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Nickname.RAW_CONTACT_ID, backReferenceIndex);
10801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Nickname.CONTENT_ITEM_TYPE);
10811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Nickname.TYPE, Nickname.TYPE_DEFAULT);
10821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Nickname.NAME, mNickname);
10831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
10841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
10871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
10881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mNickname);
10891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
10911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
10921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
10931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof NicknameData)) {
10941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
10951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
10961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            NicknameData nicknameData = (NicknameData) obj;
10971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.equals(mNickname, nicknameData.mNickname);
10981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
10991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1101517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1102517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return mNickname != null ? mNickname.hashCode() : 0;
1103517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1104517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1105517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
11061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
11071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return "nickname: " + mNickname;
11081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
11111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel() {
11121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.NICKNAME;
11131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getNickname() {
11161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mNickname;
11171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
11191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class NoteData implements EntryElement {
11211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public final String mNote;
11221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public NoteData(String note) {
11241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNote = note;
11251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
11281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
11291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
11301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
11311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
11321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Note.RAW_CONTACT_ID, backReferenceIndex);
11331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Note.CONTENT_ITEM_TYPE);
11341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Note.NOTE, mNote);
11351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
11361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
11391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
11401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mNote);
11411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
11441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
11451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
11461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
11471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
11481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof NoteData)) {
11491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
11501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
11511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            NoteData noteData = (NoteData) obj;
11521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.equals(mNote, noteData.mNote);
11531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1156517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1157517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return mNote != null ? mNote.hashCode() : 0;
1158517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1159517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1160517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
11611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
11621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return "note: " + mNote;
11631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
11661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel() {
11671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.NOTE;
11681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getNote() {
11711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mNote;
11721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
11741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class WebsiteData implements EntryElement {
11761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mWebsite;
11771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public WebsiteData(String website) {
11791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mWebsite = website;
11801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
11831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
11841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
11851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
11861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
11871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Website.RAW_CONTACT_ID, backReferenceIndex);
11881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Website.CONTENT_ITEM_TYPE);
11891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Website.URL, mWebsite);
11901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // There's no information about the type of URL in vCard.
11911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // We use TYPE_HOMEPAGE for safety.
11921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Website.TYPE, Website.TYPE_HOMEPAGE);
11931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
11941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
11951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
11961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
11971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
11981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mWebsite);
11991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
12021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
12031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
12041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
12051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
12061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof WebsiteData)) {
12071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
12081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
12091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            WebsiteData websiteData = (WebsiteData) obj;
12101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.equals(mWebsite, websiteData.mWebsite);
12111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1214517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1215517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return mWebsite != null ? mWebsite.hashCode() : 0;
1216517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1217517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1218517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
12191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
12201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return "website: " + mWebsite;
12211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
12241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel() {
12251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.WEBSITE;
12261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getWebsite() {
12291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mWebsite;
12301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
12321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class BirthdayData implements EntryElement {
12341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mBirthday;
12351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public BirthdayData(String birthday) {
12371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBirthday = birthday;
12381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
12411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
12421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
12431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
12441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
12451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Event.RAW_CONTACT_ID, backReferenceIndex);
12461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
12471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Event.START_DATE, mBirthday);
12481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Event.TYPE, Event.TYPE_BIRTHDAY);
12491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
12501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
12531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
12541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mBirthday);
12551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
12581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
12591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
12601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
12611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
12621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof BirthdayData)) {
12631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
12641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
12651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            BirthdayData birthdayData = (BirthdayData) obj;
12661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.equals(mBirthday, birthdayData.mBirthday);
12671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1270517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1271517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return mBirthday != null ? mBirthday.hashCode() : 0;
1272517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1273517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1274517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
12751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
12761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return "birthday: " + mBirthday;
12771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
12801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel() {
12811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.BIRTHDAY;
12821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getBirthday() {
12851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mBirthday;
12861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
12881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class AnniversaryData implements EntryElement {
12901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mAnniversary;
12911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public AnniversaryData(String anniversary) {
12931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mAnniversary = anniversary;
12941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
12951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
12961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
12971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
12981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
12991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
13001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
13011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(Event.RAW_CONTACT_ID, backReferenceIndex);
13021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
13031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Event.START_DATE, mAnniversary);
13041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Event.TYPE, Event.TYPE_ANNIVERSARY);
13051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
13061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
13091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
13101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mAnniversary);
13111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
13141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
13151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
13161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
13171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
13181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof AnniversaryData)) {
13191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
13201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
13211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            AnniversaryData anniversaryData = (AnniversaryData) obj;
13221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.equals(mAnniversary, anniversaryData.mAnniversary);
13231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1326517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1327517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return mAnniversary != null ? mAnniversary.hashCode() : 0;
1328517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1329517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1330517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
13311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
13321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return "anniversary: " + mAnniversary;
13331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
13361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel() {
13371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.ANNIVERSARY;
13381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getAnniversary() { return mAnniversary; }
13411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
13421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class SipData implements EntryElement {
13441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
13451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * Note that schema part ("sip:") is automatically removed. e.g.
13461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * "sip:username:password@host:port" becomes
13471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * "username:password@host:port"
13481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
13491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mAddress;
13501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mType;
13511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mLabel;
13521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final boolean mIsPrimary;
13531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public SipData(String rawSip, int type, String label, boolean isPrimary) {
13551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (rawSip.startsWith("sip:")) {
13561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mAddress = rawSip.substring(4);
13571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            } else {
13581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mAddress = rawSip;
13591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
13601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mType = type;
13611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mLabel = label;
13621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mIsPrimary = isPrimary;
13631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
13661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
13671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
13681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
13691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
13701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(SipAddress.RAW_CONTACT_ID, backReferenceIndex);
13711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, SipAddress.CONTENT_ITEM_TYPE);
13721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(SipAddress.SIP_ADDRESS, mAddress);
13731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(SipAddress.TYPE, mType);
13741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mType == SipAddress.TYPE_CUSTOM) {
13751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(SipAddress.LABEL, mLabel);
13761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
13771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mIsPrimary) {
13781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.withValue(SipAddress.IS_PRIMARY, mIsPrimary);
13791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
13801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
13811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
13841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
13851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mAddress);
13861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
13871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
13881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
13891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
13901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
13911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
13921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
13931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof SipData)) {
13941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
13951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
13961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            SipData sipData = (SipData) obj;
1397517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return (mType == sipData.mType
1398517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.equals(mLabel, sipData.mLabel)
1399517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && TextUtils.equals(mAddress, sipData.mAddress)
1400517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    && (mIsPrimary == sipData.mIsPrimary));
1401517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1402517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1403517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
1404517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1405517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mType;
1406517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mLabel != null ? mLabel.hashCode() : 0);
1407517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mAddress != null ? mAddress.hashCode() : 0);
1408517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
1409517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
14101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
14111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
14131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
14141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return "sip: " + mAddress;
14151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
14161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
14181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel() {
14191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.SIP;
14201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
14211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
14231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * @return Address part of the sip data. The schema ("sip:") isn't contained here.
14241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
14251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getAddress() { return mAddress; }
14261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public int getType() { return mType; }
14271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getLabel() { return mLabel; }
14281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
14291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    /**
14311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * Some Contacts data in Android cannot be converted to vCard
14321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * representation. VCardEntry preserves those data using this class.
14331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     */
14341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public static class AndroidCustomData implements EntryElement {
14351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final String mMimeType;
14361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final List<String> mDataList; // 1 .. VCardConstants.MAX_DATA_COLUMN
14381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public AndroidCustomData(String mimeType, List<String> dataList) {
14401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mMimeType = mimeType;
14411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mDataList = dataList;
14421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
14431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public static AndroidCustomData constructAndroidCustomData(List<String> list) {
14451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            String mimeType;
14461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            List<String> dataList;
14471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (list == null) {
14491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mimeType = null;
14501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                dataList = null;
14511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            } else if (list.size() < 2) {
14521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mimeType = list.get(0);
14531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                dataList = null;
14541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            } else {
14551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final int max = (list.size() < VCardConstants.MAX_DATA_COLUMN + 1) ? list.size()
14561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        : VCardConstants.MAX_DATA_COLUMN + 1;
14571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mimeType = list.get(0);
14581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                dataList = list.subList(1, max);
14591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
14601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return new AndroidCustomData(mimeType, dataList);
14621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
14631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
14651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void constructInsertOperation(List<ContentProviderOperation> operationList,
14661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
14671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final ContentProviderOperation.Builder builder = ContentProviderOperation
14681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .newInsert(Data.CONTENT_URI);
14691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValueBackReference(GroupMembership.RAW_CONTACT_ID, backReferenceIndex);
14701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.withValue(Data.MIMETYPE, mMimeType);
14711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            for (int i = 0; i < mDataList.size(); i++) {
14721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                String value = mDataList.get(i);
14731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (!TextUtils.isEmpty(value)) {
14741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    // 1-origin
14751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    builder.withValue("data" + (i + 1), value);
14764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
14774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
14781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            operationList.add(builder.build());
14791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
14804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
14811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
14821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean isEmpty() {
14831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return TextUtils.isEmpty(mMimeType) || mDataList == null || mDataList.size() == 0;
14841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
14851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
14861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
14871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean equals(Object obj) {
14881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (this == obj) {
14891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
14901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
14911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!(obj instanceof AndroidCustomData)) {
14921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
14931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
14941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            AndroidCustomData data = (AndroidCustomData) obj;
14951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!TextUtils.equals(mMimeType, data.mMimeType)) {
14961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
14971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
14981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (mDataList == null) {
14991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return data.mDataList == null;
15001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            } else {
15011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final int size = mDataList.size();
15021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (size != data.mDataList.size()) {
15031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    return false;
15041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
15051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                for (int i = 0; i < size; i++) {
15061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    if (!TextUtils.equals(mDataList.get(i), data.mDataList.get(i))) {
15071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        return false;
15081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    }
15094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
15101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
15114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
15121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
15134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
15141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
1515517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        public int hashCode() {
1516517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            int hash = mMimeType != null ? mMimeType.hashCode() : 0;
1517517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            if (mDataList != null) {
1518517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                for (String data : mDataList) {
1519517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                    hash = hash * 31 + (data != null ? data.hashCode() : 0);
1520517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa                }
1521517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            }
1522517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            return hash;
1523517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        }
1524517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa
1525517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa        @Override
15261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String toString() {
15271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final StringBuilder builder = new StringBuilder();
15281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.append("android-custom: " + mMimeType + ", data: ");
15291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            builder.append(mDataList == null ? "null" : Arrays.toString(mDataList.toArray()));
15304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return builder.toString();
15314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
15324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
15334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
15341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public EntryLabel getEntryLabel() {
15351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return EntryLabel.ANDROID_CUSTOM;
15364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
15371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
15381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public String getMimeType() { return mMimeType; }
15391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public List<String> getDataList() { return mDataList; }
15404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
15414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
15421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private final NameData mNameData = new NameData();
15431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<PhoneData> mPhoneList;
15441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<EmailData> mEmailList;
15451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<PostalData> mPostalList;
15461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<OrganizationData> mOrganizationList;
15471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<ImData> mImList;
15481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<PhotoData> mPhotoList;
15491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<WebsiteData> mWebsiteList;
15501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<SipData> mSipList;
15511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<NicknameData> mNicknameList;
15521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<NoteData> mNoteList;
15531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<AndroidCustomData> mAndroidCustomDataList;
15541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private BirthdayData mBirthday;
15551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private AnniversaryData mAnniversary;
1556600d08e46f52d510598ffe382bf83f576f7ab8a6Rakesh Iyer    private List<Pair<String, String>> mUnknownXData;
15574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
15581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    /**
15591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * Inner iterator interface.
15601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     */
15611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public interface EntryElementIterator {
15621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationStarted();
15631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
15641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationEnded();
15651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
15661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
15671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * Called when there are one or more {@link EntryElement} instances
15681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * associated with {@link EntryLabel}.
15691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
15701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupStarted(EntryLabel label);
15711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
15721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
15731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * Called after all {@link EntryElement} instances for
15741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * {@link EntryLabel} provided on {@link #onElementGroupStarted(EntryLabel)}
15751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * being processed by {@link #onElement(EntryElement)}
15761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
15771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupEnded();
15781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
15791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        /**
15801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         * @return should be true when child wants to continue the operation.
15811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         *         False otherwise.
15821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa         */
15831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean onElement(EntryElement elem);
15841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
15854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
15861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public final void iterateAllData(EntryElementIterator iterator) {
15871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterator.onIterationStarted();
15881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterator.onElementGroupStarted(mNameData.getEntryLabel());
15891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterator.onElement(mNameData);
15901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterator.onElementGroupEnded();
15911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
15921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mPhoneList, iterator);
15931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mEmailList, iterator);
15941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mPostalList, iterator);
15951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mOrganizationList, iterator);
15961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mImList, iterator);
15971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mPhotoList, iterator);
15981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mWebsiteList, iterator);
15991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mSipList, iterator);
16001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mNicknameList, iterator);
16011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mNoteList, iterator);
16021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateOneList(mAndroidCustomDataList, iterator);
16031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
16041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mBirthday != null) {
16051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElementGroupStarted(mBirthday.getEntryLabel());
16061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElement(mBirthday);
16071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElementGroupEnded();
16081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
16091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mAnniversary != null) {
16101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElementGroupStarted(mAnniversary.getEntryLabel());
16111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElement(mAnniversary);
16121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElementGroupEnded();
16131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
16141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterator.onIterationEnded();
16151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
16161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
16171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private void iterateOneList(List<? extends EntryElement> elemList,
16181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            EntryElementIterator iterator) {
16191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (elemList != null && elemList.size() > 0) {
16201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElementGroupStarted(elemList.get(0).getEntryLabel());
16211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            for (EntryElement elem : elemList) {
16221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                iterator.onElement(elem);
16234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
16241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            iterator.onElementGroupEnded();
16254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
16271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
16281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private class IsIgnorableIterator implements EntryElementIterator {
16291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private boolean mEmpty = true;
16304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
16321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationStarted() {
16334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
16361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationEnded() {
16374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
16401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupStarted(EntryLabel label) {
16414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        @Override
16441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupEnded() {
16454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
16481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean onElement(EntryElement elem) {
16491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!elem.isEmpty()) {
16501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mEmpty = false;
16511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                // exit now
16521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return false;
16534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
16541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return true;
16554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
16564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean getResult() {
16591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mEmpty;
16604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
16621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
16631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private class ToStringIterator implements EntryElementIterator {
16641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private StringBuilder mBuilder;
16651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
16661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private boolean mFirstElement;
16674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
16691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationStarted() {
16701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBuilder = new StringBuilder();
16711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBuilder.append("[[hash: " + VCardEntry.this.hashCode() + "\n");
167248dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        }
167348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
16741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
16751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupStarted(EntryLabel label) {
16761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBuilder.append(label.toString() + ": ");
16771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mFirstElement = true;
16784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
16811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean onElement(EntryElement elem) {
16821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!mFirstElement) {
16831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mBuilder.append(", ");
16841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mFirstElement = false;
16851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
16861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBuilder.append("[").append(elem.toString()).append("]");
16871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return true;
16884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
16911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupEnded() {
16921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBuilder.append("\n");
16934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
16944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
16951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
16961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationEnded() {
16971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBuilder.append("]]\n");
16984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
169948dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
170048dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        @Override
170148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        public String toString() {
17021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return mBuilder.toString();
170348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        }
17044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
17054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private class InsertOperationConstrutor implements EntryElementIterator {
17071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final List<ContentProviderOperation> mOperationList;
17084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        private final int mBackReferenceIndex;
17104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public InsertOperationConstrutor(List<ContentProviderOperation> operationList,
17121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                int backReferenceIndex) {
17131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mOperationList = operationList;
17141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBackReferenceIndex = backReferenceIndex;
17151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
17164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
17181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationStarted() {
17191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
17204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
17221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onIterationEnded() {
17231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
17244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
17261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupStarted(EntryLabel label) {
17271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
17284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
17301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public void onElementGroupEnded() {
17311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
17324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        @Override
17341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        public boolean onElement(EntryElement elem) {
17351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (!elem.isEmpty()) {
17361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                elem.constructInsertOperation(mOperationList, mBackReferenceIndex);
17371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
17381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return true;
17391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
17401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
17414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private final int mVCardType;
17434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private final Account mAccount;
17444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
174548dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    private List<VCardEntry> mChildren;
174648dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
174748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
174848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    public String toString() {
17491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        ToStringIterator iterator = new ToStringIterator();
17501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateAllData(iterator);
17511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return iterator.toString();
175248dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    }
175348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
17544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public VCardEntry() {
17554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        this(VCardConfig.VCARD_TYPE_V21_GENERIC);
17564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
17574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public VCardEntry(int vcardType) {
17594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        this(vcardType, null);
17604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
17614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public VCardEntry(int vcardType, Account account) {
17634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mVCardType = vcardType;
17644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mAccount = account;
17654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
17664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
17674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void addPhone(int type, String data, String label, boolean isPrimary) {
17684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mPhoneList == null) {
17694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mPhoneList = new ArrayList<PhoneData>();
17704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
17714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        final StringBuilder builder = new StringBuilder();
177295e66b00988bc16ecc17df31e47c873b2554b8ccinshik        final String trimmed = data.trim();
17734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        final String formattedNumber;
17744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (type == Phone.TYPE_PAGER || VCardConfig.refrainPhoneNumberFormatting(mVCardType)) {
177595e66b00988bc16ecc17df31e47c873b2554b8ccinshik            formattedNumber = trimmed;
17764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
177795e66b00988bc16ecc17df31e47c873b2554b8ccinshik            // TODO: from the view of vCard spec these auto conversions should be removed.
177895e66b00988bc16ecc17df31e47c873b2554b8ccinshik            // Note that some other codes (like the phone number formatter) or modules expect this
177995e66b00988bc16ecc17df31e47c873b2554b8ccinshik            // auto conversion (bug 5178723), so just omitting this code won't be preferable enough
178095e66b00988bc16ecc17df31e47c873b2554b8ccinshik            // (bug 4177894)
178195e66b00988bc16ecc17df31e47c873b2554b8ccinshik            boolean hasPauseOrWait = false;
178295e66b00988bc16ecc17df31e47c873b2554b8ccinshik            final int length = trimmed.length();
17834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            for (int i = 0; i < length; i++) {
178495e66b00988bc16ecc17df31e47c873b2554b8ccinshik                char ch = trimmed.charAt(i);
178595e66b00988bc16ecc17df31e47c873b2554b8ccinshik                // See RFC 3601 and docs for PhoneNumberUtils for more info.
178695e66b00988bc16ecc17df31e47c873b2554b8ccinshik                if (ch == 'p' || ch == 'P') {
178795e66b00988bc16ecc17df31e47c873b2554b8ccinshik                    builder.append(PhoneNumberUtils.PAUSE);
178895e66b00988bc16ecc17df31e47c873b2554b8ccinshik                    hasPauseOrWait = true;
178995e66b00988bc16ecc17df31e47c873b2554b8ccinshik                } else if (ch == 'w' || ch == 'W') {
179095e66b00988bc16ecc17df31e47c873b2554b8ccinshik                    builder.append(PhoneNumberUtils.WAIT);
179195e66b00988bc16ecc17df31e47c873b2554b8ccinshik                    hasPauseOrWait = true;
1792f4d2a98d3088641e86fed2ca26ca368b289a9aecJoseph Pirozzo                } else if (PhoneNumberUtils.is12Key(ch) || (i == 0 && ch == '+')) {
17934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    builder.append(ch);
17944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
17954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
179695e66b00988bc16ecc17df31e47c873b2554b8ccinshik            if (!hasPauseOrWait) {
179795e66b00988bc16ecc17df31e47c873b2554b8ccinshik                final int formattingType = VCardUtils.getPhoneNumberFormat(mVCardType);
179895e66b00988bc16ecc17df31e47c873b2554b8ccinshik                formattedNumber = PhoneNumberUtilsPort.formatNumber(
179995e66b00988bc16ecc17df31e47c873b2554b8ccinshik                        builder.toString(), formattingType);
180095e66b00988bc16ecc17df31e47c873b2554b8ccinshik            } else {
180195e66b00988bc16ecc17df31e47c873b2554b8ccinshik                formattedNumber = builder.toString();
180295e66b00988bc16ecc17df31e47c873b2554b8ccinshik            }
18031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
18041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        PhoneData phoneData = new PhoneData(formattedNumber, type, label, isPrimary);
18054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mPhoneList.add(phoneData);
18064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
18074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
18081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private void addSip(String sipData, int type, String label, boolean isPrimary) {
18091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mSipList == null) {
18101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mSipList = new ArrayList<SipData>();
18111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
18121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mSipList.add(new SipData(sipData, type, label, isPrimary));
18131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
18141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
18154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void addNickName(final String nickName) {
18161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mNicknameList == null) {
18171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNicknameList = new ArrayList<NicknameData>();
18184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
18191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mNicknameList.add(new NicknameData(nickName));
18204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
18214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
18221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private void addEmail(int type, String data, String label, boolean isPrimary) {
18234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mEmailList == null) {
18244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mEmailList = new ArrayList<EmailData>();
18254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
18261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mEmailList.add(new EmailData(data, type, label, isPrimary));
18274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
18284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
18291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private void addPostal(int type, List<String> propValueList, String label, boolean isPrimary) {
18304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mPostalList == null) {
18314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mPostalList = new ArrayList<PostalData>(0);
18324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
18331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mPostalList.add(PostalData.constructPostalData(propValueList, type, label, isPrimary,
18341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mVCardType));
18354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
18364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
18374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
183802117b3d19787ff65486b9f9db8abd338ae4c9f9Daisuke Miyakawa     * Should be called via {@link #handleOrgValue(int, List, Map, boolean)} or
18394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * {@link #handleTitleValue(String)}.
18404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
18411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private void addNewOrganization(final String organizationName, final String departmentName,
18421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final String titleName, final String phoneticName, int type, final boolean isPrimary) {
18434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mOrganizationList == null) {
18444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mOrganizationList = new ArrayList<OrganizationData>();
18454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
18461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mOrganizationList.add(new OrganizationData(organizationName, departmentName, titleName,
18471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                phoneticName, type, isPrimary));
18484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
18494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
18501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private static final List<String> sEmptyList = Collections
18511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            .unmodifiableList(new ArrayList<String>(0));
18524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
18534560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa    private String buildSinglePhoneticNameFromSortAsParam(Map<String, Collection<String>> paramMap) {
18544560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        final Collection<String> sortAsCollection = paramMap.get(VCardConstants.PARAM_SORT_AS);
18554560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        if (sortAsCollection != null && sortAsCollection.size() != 0) {
18564560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            if (sortAsCollection.size() > 1) {
18571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                Log.w(LOG_TAG,
18581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        "Incorrect multiple SORT_AS parameters detected: "
18591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                                + Arrays.toString(sortAsCollection.toArray()));
18604560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            }
18611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final List<String> sortNames = VCardUtils.constructListFromValue(sortAsCollection
18621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .iterator().next(), mVCardType);
18634560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            final StringBuilder builder = new StringBuilder();
18644560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            for (final String elem : sortNames) {
18654560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa                builder.append(elem);
18664560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            }
18674560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            return builder.toString();
18684560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        } else {
18694560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            return null;
18704560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        }
18714560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa    }
18724560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa
18734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
18741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * Set "ORG" related values to the appropriate data. If there's more than
18751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * one {@link OrganizationData} objects, this input data are attached to the
18761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * last one which does not have valid values (not including empty but only
18771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * null). If there's no {@link OrganizationData} object, a new
18781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * {@link OrganizationData} is created, whose title is set to null.
18794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
18804560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa    private void handleOrgValue(final int type, List<String> orgList,
18814560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            Map<String, Collection<String>> paramMap, boolean isPrimary) {
18824560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        final String phoneticName = buildSinglePhoneticNameFromSortAsParam(paramMap);
18834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (orgList == null) {
18844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            orgList = sEmptyList;
18854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
18861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        final String organizationName;
18874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        final String departmentName;
18884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        final int size = orgList.size();
18894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        switch (size) {
18901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 0: {
18911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            organizationName = "";
18921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            departmentName = null;
18931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            break;
18941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
18951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 1: {
18961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            organizationName = orgList.get(0);
18971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            departmentName = null;
18981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            break;
18991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
19001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        default: { // More than 1.
19011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            organizationName = orgList.get(0);
19021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // We're not sure which is the correct string for department.
19031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // In order to keep all the data, concatinate the rest of elements.
19041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            StringBuilder builder = new StringBuilder();
19051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            for (int i = 1; i < size; i++) {
19061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (i > 1) {
19071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    builder.append(' ');
19084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
19091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                builder.append(orgList.get(i));
19104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
19111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            departmentName = builder.toString();
19121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
19134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mOrganizationList == null) {
19154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // Create new first organization entry, with "null" title which may be
19164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // added via handleTitleValue().
19171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            addNewOrganization(organizationName, departmentName, null, phoneticName, type,
19181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    isPrimary);
19194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return;
19204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        for (OrganizationData organizationData : mOrganizationList) {
19224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // Not use TextUtils.isEmpty() since ORG was set but the elements might be empty.
19234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // e.g. "ORG;PREF:;" -> Both companyName and departmentName become empty but not null.
19241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (organizationData.mOrganizationName == null
19251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && organizationData.mDepartmentName == null) {
19264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // Probably the "TITLE" property comes before the "ORG" property via
19274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // handleTitleLine().
19281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                organizationData.mOrganizationName = organizationName;
19291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                organizationData.mDepartmentName = departmentName;
19301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                organizationData.mIsPrimary = isPrimary;
19314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return;
19324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
19334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // No OrganizatioData is available. Create another one, with "null" title, which may be
19354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // added via handleTitleValue().
19361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        addNewOrganization(organizationName, departmentName, null, phoneticName, type, isPrimary);
19374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
19384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
19394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
19404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * Set "title" value to the appropriate data. If there's more than one
19411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * OrganizationData objects, this input is attached to the last one which
19421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * does not have valid title value (not including empty but only null). If
19431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * there's no OrganizationData object, a new OrganizationData is created,
19441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * whose company name is set to null.
19454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
19464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void handleTitleValue(final String title) {
19474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mOrganizationList == null) {
19484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // Create new first organization entry, with "null" other info, which may be
19494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // added via handleOrgValue().
19501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            addNewOrganization(null, null, title, null, DEFAULT_ORGANIZATION_TYPE, false);
19514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return;
19524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        for (OrganizationData organizationData : mOrganizationList) {
19541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (organizationData.mTitle == null) {
19551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                organizationData.mTitle = title;
19564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return;
19574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
19584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // No Organization is available. Create another one, with "null" other info, which may be
19604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // added via handleOrgValue().
19611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        addNewOrganization(null, null, title, null, DEFAULT_ORGANIZATION_TYPE, false);
19624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
19634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
19641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private void addIm(int protocol, String customProtocol, String propValue, int type,
19651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            boolean isPrimary) {
19664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mImList == null) {
19674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mImList = new ArrayList<ImData>();
19684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mImList.add(new ImData(protocol, customProtocol, propValue, type, isPrimary));
19704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
19714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
19724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void addNote(final String note) {
19734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mNoteList == null) {
19741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNoteList = new ArrayList<NoteData>(1);
19754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mNoteList.add(new NoteData(note));
19774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
19784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
19794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void addPhotoBytes(String formatName, byte[] photoBytes, boolean isPrimary) {
19804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mPhotoList == null) {
19814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mPhotoList = new ArrayList<PhotoData>(1);
19824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        final PhotoData photoData = new PhotoData(formatName, photoBytes, isPrimary);
19844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mPhotoList.add(photoData);
19854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
19864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
19874560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa    /**
19881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * Tries to extract paramMap, constructs SORT-AS parameter values, and store
19891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * them in appropriate phonetic name variables. This method does not care
19901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * the vCard version. Even when we have SORT-AS parameters in invalid
19911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * versions (i.e. 2.1 and 3.0), we scilently accept them so that we won't
19921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * drop meaningful information. If we had this parameter in the N field of
19931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * vCard 3.0, and the contact data also have SORT-STRING, we will prefer
19941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * SORT-STRING, since it is regitimate property to be understood.
19954560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa     */
19964560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa    private void tryHandleSortAsName(final Map<String, Collection<String>> paramMap) {
19971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (VCardConfig.isVersion30(mVCardType)
19981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                && !(TextUtils.isEmpty(mNameData.mPhoneticFamily)
19991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        && TextUtils.isEmpty(mNameData.mPhoneticMiddle) && TextUtils
20001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        .isEmpty(mNameData.mPhoneticGiven))) {
20014560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            return;
20024560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        }
20034560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa
20044560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        final Collection<String> sortAsCollection = paramMap.get(VCardConstants.PARAM_SORT_AS);
20054560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        if (sortAsCollection != null && sortAsCollection.size() != 0) {
20064560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            if (sortAsCollection.size() > 1) {
20071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                Log.w(LOG_TAG,
20081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        "Incorrect multiple SORT_AS parameters detected: "
20091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                                + Arrays.toString(sortAsCollection.toArray()));
20104560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            }
20111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final List<String> sortNames = VCardUtils.constructListFromValue(sortAsCollection
20121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    .iterator().next(), mVCardType);
20134560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            int size = sortNames.size();
20144560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            if (size > 3) {
20154560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa                size = 3;
20164560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            }
20174560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            switch (size) {
20181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            case 3:
20191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mNameData.mPhoneticMiddle = sortNames.get(2); //$FALL-THROUGH$
20201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            case 2:
20211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mNameData.mPhoneticGiven = sortNames.get(1); //$FALL-THROUGH$
20221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            default:
20231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mNameData.mPhoneticFamily = sortNames.get(0);
20241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                break;
20254560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            }
20264560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        }
20274560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa    }
20284560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa
20294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    @SuppressWarnings("fallthrough")
20304560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa    private void handleNProperty(final List<String> paramValues,
20314560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa            Map<String, Collection<String>> paramMap) {
20324560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        // in vCard 4.0, SORT-AS parameter is available.
20334560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        tryHandleSortAsName(paramMap);
20344560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa
20354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // Family, Given, Middle, Prefix, Suffix. (1 - 5)
20364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        int size;
20374560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        if (paramValues == null || (size = paramValues.size()) < 1) {
20384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return;
20394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
20404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (size > 5) {
20414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            size = 5;
20424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
20434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
20444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        switch (size) {
20454560bdde6dd75cca49fc55b58aafb5d416b88ca3Daisuke Miyakawa        // Fall-through.
20461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 5:
20471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mSuffix = paramValues.get(4);
20481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 4:
20491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mPrefix = paramValues.get(3);
20501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 3:
20511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mMiddle = paramValues.get(2);
20521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 2:
20531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mGiven = paramValues.get(1);
20541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        default:
20551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mFamily = paramValues.get(0);
20564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
20574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
20584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
20594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
20601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * Note: Some Japanese mobile phones use this field for phonetic name, since
20611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * vCard 2.1 does not have "SORT-STRING" type. Also, in some cases, the
20621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * field has some ';'s in it. Assume the ';' means the same meaning in N
20631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * property
20644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
20654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    @SuppressWarnings("fallthrough")
20664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void handlePhoneticNameFromSound(List<String> elems) {
20671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (!(TextUtils.isEmpty(mNameData.mPhoneticFamily)
20681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                && TextUtils.isEmpty(mNameData.mPhoneticMiddle) && TextUtils
20691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                .isEmpty(mNameData.mPhoneticGiven))) {
20704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // This means the other properties like "X-PHONETIC-FIRST-NAME" was already found.
20714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // Ignore "SOUND;X-IRMC-N".
20724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return;
20734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
20744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
20754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        int size;
20764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (elems == null || (size = elems.size()) < 1) {
20774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return;
20784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
20794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
20804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // Assume that the order is "Family, Given, Middle".
20811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // This is not from specification but mere assumption. Some Japanese
20821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // phones use this order.
20834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (size > 3) {
20844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            size = 3;
20854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
20864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
20874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (elems.get(0).length() > 0) {
20884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            boolean onlyFirstElemIsNonEmpty = true;
20894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            for (int i = 1; i < size; i++) {
20904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (elems.get(i).length() > 0) {
20914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    onlyFirstElemIsNonEmpty = false;
20924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    break;
20934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
20944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
20954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (onlyFirstElemIsNonEmpty) {
20964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                final String[] namesArray = elems.get(0).split(" ");
20974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                final int nameArrayLength = namesArray.length;
20984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (nameArrayLength == 3) {
20994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    // Assume the string is "Family Middle Given".
21001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mPhoneticFamily = namesArray[0];
21011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mPhoneticMiddle = namesArray[1];
21021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mPhoneticGiven = namesArray[2];
21034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                } else if (nameArrayLength == 2) {
21044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    // Assume the string is "Family Given" based on the Japanese mobile
21054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    // phones' preference.
21061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mPhoneticFamily = namesArray[0];
21071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mPhoneticGiven = namesArray[1];
21084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                } else {
21091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mPhoneticGiven = elems.get(0);
21104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
21114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return;
21124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
21134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
21144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
21154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        switch (size) {
21161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // fallthrough
21171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 3:
21181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mPhoneticMiddle = elems.get(2);
21191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        case 2:
21201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mPhoneticGiven = elems.get(1);
21211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        default:
21221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mPhoneticFamily = elems.get(0);
21234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
21244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
21254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
21261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void addProperty(final VCardProperty property) {
21271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        final String propertyName = property.getName();
21281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        final Map<String, Collection<String>> paramMap = property.getParameterMap();
21291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        final List<String> propertyValueList = property.getValueList();
21301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        byte[] propertyBytes = property.getByteValue();
21314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
21321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if ((propertyValueList == null || propertyValueList.size() == 0)
21331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                && propertyBytes == null) {
21344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return;
21354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
21361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        final String propValue = (propertyValueList != null
21371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                ? listToString(propertyValueList).trim()
21381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                : null);
21394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
21401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (propertyName.equals(VCardConstants.PROPERTY_VERSION)) {
21414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // vCard version. Ignore this.
21421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_FN)) {
21431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mFormatted = propValue;
21441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_NAME)) {
21451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // Only in vCard 3.0. Use this if FN doesn't exist though it is
21461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            // required in vCard 3.0.
21471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (TextUtils.isEmpty(mNameData.mFormatted)) {
21481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mNameData.mFormatted = propValue;
21491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
21501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_N)) {
21511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            handleNProperty(propertyValueList, paramMap);
21521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_SORT_STRING)) {
2153517540b6e3903371def5eb4ca44c2bb2ff91ae30Daisuke Miyakawa            mNameData.mSortString = propValue;
21541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_NICKNAME)
21551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                || propertyName.equals(VCardConstants.ImportOnly.PROPERTY_X_NICKNAME)) {
21564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            addNickName(propValue);
21571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_SOUND)) {
21584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
21594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (typeCollection != null
21604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    && typeCollection.contains(VCardConstants.PARAM_TYPE_X_IRMC_N)) {
21614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // As of 2009-10-08, Parser side does not split a property value into separated
21624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // values using ';' (in other words, propValueList.size() == 1),
21634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // which is correct behavior from the view of vCard 2.1.
21644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // But we want it to be separated, so do the separation here.
21651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final List<String> phoneticNameList = VCardUtils.constructListFromValue(propValue,
21661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        mVCardType);
21674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                handlePhoneticNameFromSound(phoneticNameList);
21684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
21694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // Ignore this field since Android cannot understand what it is.
21704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
21711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_ADR)) {
21724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            boolean valuesAreAllEmpty = true;
21731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            for (String value : propertyValueList) {
21741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (!TextUtils.isEmpty(value)) {
21754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    valuesAreAllEmpty = false;
21764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    break;
21774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
21784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
21794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (valuesAreAllEmpty) {
21804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return;
21814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
21824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
21834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            int type = -1;
21841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            String label = null;
21854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            boolean isPrimary = false;
218600b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa            final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
21874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (typeCollection != null) {
218800b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                for (final String typeStringOrg : typeCollection) {
218900b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    final String typeStringUpperCase = typeStringOrg.toUpperCase();
219000b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_PREF)) {
21914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        isPrimary = true;
219200b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_HOME)) {
21934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        type = StructuredPostal.TYPE_HOME;
21941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        label = null;
21951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_WORK)
21961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                            || typeStringUpperCase
21971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                                    .equalsIgnoreCase(VCardConstants.PARAM_EXTRA_TYPE_COMPANY)) {
21984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        // "COMPANY" seems emitted by Windows Mobile, which is not
21994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        // specifically supported by vCard 2.1. We assume this is same
22004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        // as "WORK".
22014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        type = StructuredPostal.TYPE_WORK;
22021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        label = null;
22031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_ADR_TYPE_PARCEL)
22041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                            || typeStringUpperCase.equals(VCardConstants.PARAM_ADR_TYPE_DOM)
22051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                            || typeStringUpperCase.equals(VCardConstants.PARAM_ADR_TYPE_INTL)) {
22064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        // We do not have any appropriate way to store this information.
22071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    } else if (type < 0) { // If no other type is specified before.
22084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        type = StructuredPostal.TYPE_CUSTOM;
22091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        if (typeStringUpperCase.startsWith("X-")) { // If X- or x-
221000b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                            label = typeStringOrg.substring(2);
221100b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                        } else {
221200b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                            label = typeStringOrg;
221300b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                        }
22144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
22154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
22164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
22174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // We use "HOME" as default
22184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (type < 0) {
22194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                type = StructuredPostal.TYPE_HOME;
22204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
22214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
22221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            addPostal(type, propertyValueList, label, isPrimary);
22231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_EMAIL)) {
22244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            int type = -1;
22254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            String label = null;
22264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            boolean isPrimary = false;
222700b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa            final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
22284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (typeCollection != null) {
222900b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                for (final String typeStringOrg : typeCollection) {
223000b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    final String typeStringUpperCase = typeStringOrg.toUpperCase();
223100b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_PREF)) {
22324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        isPrimary = true;
223300b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_HOME)) {
22344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        type = Email.TYPE_HOME;
223500b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_WORK)) {
22364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        type = Email.TYPE_WORK;
223700b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_CELL)) {
22384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        type = Email.TYPE_MOBILE;
22391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    } else if (type < 0) { // If no other type is specified before
22401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        if (typeStringUpperCase.startsWith("X-")) { // If X- or x-
224100b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                            label = typeStringOrg.substring(2);
224200b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                        } else {
224300b4b98ea94df7fa3f88ee9a623d60db0d4fc451Daisuke Miyakawa                            label = typeStringOrg;
22444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        }
22454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        type = Email.TYPE_CUSTOM;
22464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
22474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
22484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
22494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (type < 0) {
22504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                type = Email.TYPE_OTHER;
22514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
22524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            addEmail(type, propValue, label, isPrimary);
22531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_ORG)) {
22544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // vCard specification does not specify other types.
22554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final int type = Organization.TYPE_WORK;
22564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            boolean isPrimary = false;
22574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
22584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (typeCollection != null) {
22594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                for (String typeString : typeCollection) {
22604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) {
22614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        isPrimary = true;
22624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
22634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
22644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
22651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            handleOrgValue(type, propertyValueList, paramMap, isPrimary);
22661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_TITLE)) {
22674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            handleTitleValue(propValue);
22681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_ROLE)) {
22694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // This conflicts with TITLE. Ignore for now...
22704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // handleTitleValue(propValue);
22711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_PHOTO)
22721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                || propertyName.equals(VCardConstants.PROPERTY_LOGO)) {
22734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            Collection<String> paramMapValue = paramMap.get("VALUE");
22744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (paramMapValue != null && paramMapValue.contains("URL")) {
22754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // Currently we do not have appropriate example for testing this case.
22764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
22774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                final Collection<String> typeCollection = paramMap.get("TYPE");
22784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                String formatName = null;
22794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                boolean isPrimary = false;
22804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (typeCollection != null) {
22814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    for (String typeValue : typeCollection) {
22824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        if (VCardConstants.PARAM_TYPE_PREF.equals(typeValue)) {
22834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            isPrimary = true;
22841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        } else if (formatName == null) {
22854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            formatName = typeValue;
22864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        }
22874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
22884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
22891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                addPhotoBytes(formatName, propertyBytes, isPrimary);
22904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
22911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_TEL)) {
22921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            String phoneNumber = null;
22931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            boolean isSip = false;
229437634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa            if (VCardConfig.isVersion40(mVCardType)) {
229537634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                // Given propValue is in URI format, not in phone number format used until
229637634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                // vCard 3.0.
22971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (propValue.startsWith("sip:")) {
22981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    isSip = true;
229937634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                } else if (propValue.startsWith("tel:")) {
230037634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                    phoneNumber = propValue.substring(4);
230137634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                } else {
230237634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                    // We don't know appropriate way to handle the other schemas. Also,
230337634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                    // we may still have non-URI phone number. To keep given data as much as
230437634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                    // we can, just save original value here.
230537634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                    phoneNumber = propValue;
230637634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                }
230737634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa            } else {
230837634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                phoneNumber = propValue;
230937634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa            }
231037634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa
23111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (isSip) {
23121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
23131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                handleSipCase(propValue, typeCollection);
23144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
23151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (propValue.length() == 0) {
23161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    return;
23171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
23184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
23191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
23201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final Object typeObject = VCardUtils.getPhoneTypeFromStrings(typeCollection,
23211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        phoneNumber);
23221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final int type;
23231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final String label;
23241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (typeObject instanceof Integer) {
23251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    type = (Integer) typeObject;
23261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    label = null;
23271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                } else {
23281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    type = Phone.TYPE_CUSTOM;
23291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    label = typeObject.toString();
23301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
23311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
23321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final boolean isPrimary;
23331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (typeCollection != null &&
23341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        typeCollection.contains(VCardConstants.PARAM_TYPE_PREF)) {
23351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    isPrimary = true;
23361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                } else {
23371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    isPrimary = false;
23381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
23391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
23401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                addPhone(type, phoneNumber, label, isPrimary);
23414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
23421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_X_SKYPE_PSTNNUMBER)) {
23434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // The phone number available via Skype.
23444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
23454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final int type = Phone.TYPE_OTHER;
23464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final boolean isPrimary;
23471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (typeCollection != null
23481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    && typeCollection.contains(VCardConstants.PARAM_TYPE_PREF)) {
23494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                isPrimary = true;
23504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
23514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                isPrimary = false;
23524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
23534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            addPhone(type, propValue, null, isPrimary);
23541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (sImMap.containsKey(propertyName)) {
23551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final int protocol = sImMap.get(propertyName);
23564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            boolean isPrimary = false;
23574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            int type = -1;
23584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
23594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (typeCollection != null) {
23604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                for (String typeString : typeCollection) {
23614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) {
23624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        isPrimary = true;
23634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    } else if (type < 0) {
23644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        if (typeString.equalsIgnoreCase(VCardConstants.PARAM_TYPE_HOME)) {
23654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            type = Im.TYPE_HOME;
23664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        } else if (typeString.equalsIgnoreCase(VCardConstants.PARAM_TYPE_WORK)) {
23674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                            type = Im.TYPE_WORK;
23684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        }
23694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    }
23704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
23714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
23724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (type < 0) {
237306ae82316d0b5f7222a7a1d15b7d03df88fdea15Daisuke Miyakawa                type = Im.TYPE_HOME;
23744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
23751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            addIm(protocol, null, propValue, type, isPrimary);
23761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_NOTE)) {
23774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            addNote(propValue);
23781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_URL)) {
23794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (mWebsiteList == null) {
23801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                mWebsiteList = new ArrayList<WebsiteData>(1);
23811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
23821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mWebsiteList.add(new WebsiteData(propValue));
23831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_BDAY)) {
23841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mBirthday = new BirthdayData(propValue);
23851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_ANNIVERSARY)) {
23861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mAnniversary = new AnniversaryData(propValue);
23871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_X_PHONETIC_FIRST_NAME)) {
23881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mPhoneticGiven = propValue;
23891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_X_PHONETIC_MIDDLE_NAME)) {
23901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mPhoneticMiddle = propValue;
23911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_X_PHONETIC_LAST_NAME)) {
23921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.mPhoneticFamily = propValue;
23931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_IMPP)) {
239488d0f1ef715f2e1209eba5d175b1b71c556fa8b0Daisuke Miyakawa            // See also RFC 4770 (for vCard 3.0)
23951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (propValue.startsWith("sip:")) {
23961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
23971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                handleSipCase(propValue, typeCollection);
239888d0f1ef715f2e1209eba5d175b1b71c556fa8b0Daisuke Miyakawa            }
23991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_X_SIP)) {
24005db8b7baeffb35191032789cb0b0d643b78f0120Daisuke Miyakawa            if (!TextUtils.isEmpty(propValue)) {
24011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
24021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                handleSipCase(propValue, typeCollection);
24031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
24041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (propertyName.equals(VCardConstants.PROPERTY_X_ANDROID_CUSTOM)) {
24051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            final List<String> customPropertyList = VCardUtils.constructListFromValue(propValue,
24061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mVCardType);
24071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            handleAndroidCustomProperty(customPropertyList);
2408600d08e46f52d510598ffe382bf83f576f7ab8a6Rakesh Iyer        } else if (propertyName.toUpperCase().startsWith("X-")) {
2409600d08e46f52d510598ffe382bf83f576f7ab8a6Rakesh Iyer            // Catch all for X- properties. The caller can decide what to do with these.
2410600d08e46f52d510598ffe382bf83f576f7ab8a6Rakesh Iyer            if (mUnknownXData == null) {
2411600d08e46f52d510598ffe382bf83f576f7ab8a6Rakesh Iyer                mUnknownXData = new ArrayList<Pair<String, String>>();
2412600d08e46f52d510598ffe382bf83f576f7ab8a6Rakesh Iyer            }
2413600d08e46f52d510598ffe382bf83f576f7ab8a6Rakesh Iyer            mUnknownXData.add(new Pair<String, String>(propertyName, propValue));
24141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else {
24151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
24161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // Be careful when adding some logic here, as some blocks above may use "return".
24171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
24180fc278de46840f89c01aa984de7565c1f97e3103Daisuke Miyakawa
24191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    /**
24201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * @param propValue may contain "sip:" at the beginning.
24211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * @param typeCollection
24221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     */
24231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private void handleSipCase(String propValue, Collection<String> typeCollection) {
24241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (TextUtils.isEmpty(propValue)) {
24251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return;
24261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
24271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (propValue.startsWith("sip:")) {
24281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            propValue = propValue.substring(4);
24291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (propValue.length() == 0) {
24301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                return;
24311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
24321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
24331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
24341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        int type = -1;
24351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        String label = null;
24361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        boolean isPrimary = false;
24371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (typeCollection != null) {
24381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            for (final String typeStringOrg : typeCollection) {
24391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                final String typeStringUpperCase = typeStringOrg.toUpperCase();
24401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_PREF)) {
24411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    isPrimary = true;
24421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_HOME)) {
24431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    type = SipAddress.TYPE_HOME;
24441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_WORK)) {
24451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    type = SipAddress.TYPE_WORK;
24461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                } else if (type < 0) { // If no other type is specified before
24471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    if (typeStringUpperCase.startsWith("X-")) { // If X- or x-
24481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        label = typeStringOrg.substring(2);
244937634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                    } else {
24501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                        label = typeStringOrg;
245137634a0179f74431317f50d2ce493e3fad36f5a9Daisuke Miyakawa                    }
24521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    type = SipAddress.TYPE_CUSTOM;
24530fc278de46840f89c01aa984de7565c1f97e3103Daisuke Miyakawa                }
24545db8b7baeffb35191032789cb0b0d643b78f0120Daisuke Miyakawa            }
24554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
24561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (type < 0) {
24571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            type = SipAddress.TYPE_OTHER;
24581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
24591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        addSip(propValue, type, label, isPrimary);
24604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
24614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
246248dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    public void addChild(VCardEntry child) {
246348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        if (mChildren == null) {
246448dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa            mChildren = new ArrayList<VCardEntry>();
246548dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        }
246648dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        mChildren.add(child);
246748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    }
246848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
24694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private void handleAndroidCustomProperty(final List<String> customPropertyList) {
24701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mAndroidCustomDataList == null) {
24711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mAndroidCustomDataList = new ArrayList<AndroidCustomData>();
24724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
24731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mAndroidCustomDataList
24741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                .add(AndroidCustomData.constructAndroidCustomData(customPropertyList));
24754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
24764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
24774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
24784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * Construct the display name. The constructed data must not be null.
24794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
24801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private String constructDisplayName() {
24811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        String displayName = null;
24824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // FullName (created via "FN" or "NAME" field) is prefered.
24831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (!TextUtils.isEmpty(mNameData.mFormatted)) {
24841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = mNameData.mFormatted;
24851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (!mNameData.emptyStructuredName()) {
24861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = VCardUtils.constructNameFromElements(mVCardType, mNameData.mFamily,
24871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mMiddle, mNameData.mGiven, mNameData.mPrefix, mNameData.mSuffix);
24881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else if (!mNameData.emptyPhoneticStructuredName()) {
24891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = VCardUtils.constructNameFromElements(mVCardType,
24901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    mNameData.mPhoneticFamily, mNameData.mPhoneticMiddle, mNameData.mPhoneticGiven);
24914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (mEmailList != null && mEmailList.size() > 0) {
24921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = mEmailList.get(0).mAddress;
24934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (mPhoneList != null && mPhoneList.size() > 0) {
24941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = mPhoneList.get(0).mNumber;
24954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (mPostalList != null && mPostalList.size() > 0) {
24961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = mPostalList.get(0).getFormattedAddress(mVCardType);
24974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (mOrganizationList != null && mOrganizationList.size() > 0) {
24981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = mOrganizationList.get(0).getFormattedString();
24994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
25001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (displayName == null) {
25011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            displayName = "";
25024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
25031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return displayName;
25044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
25054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
25064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
25074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * Consolidate several fielsds (like mName) using name candidates,
25084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
25094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void consolidateFields() {
25101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mNameData.displayName = constructDisplayName();
251148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    }
251248dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
25131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    /**
25141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * @return true when this object has nothing meaningful for Android's
25151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *         Contacts, and thus is "ignorable" for Android's Contacts. This
25161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *         does not mean an original vCard is really empty. Even when the
25171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *         original vCard has some fields, this may ignore it if those
25181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *         fields cannot be transcoded into Android's Contacts
25191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *         representation.
25201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     */
25211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public boolean isIgnorable() {
25221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        IsIgnorableIterator iterator = new IsIgnorableIterator();
25231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateAllData(iterator);
25241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return iterator.getResult();
252548dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    }
252648dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
2527f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa    /**
25281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * Constructs the list of insert operation for this object. When the
25291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * operationList argument is null, this method creates a new ArrayList and
25301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * return it. The returned object is filled with new insert operations for
25311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * this object. When operationList argument is not null, this method appends
25321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * those new operations into the object instead of creating a new ArrayList.
2533f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa     *
2534f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa     * @param resolver {@link ContentResolver} object to be used in this method.
25351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * @param operationList object to be filled. You can use this argument to
25361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *            concatinate operation lists. If null, this method creates a
25371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *            new array object.
25381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     * @return If operationList argument is null, new object with new insert
25391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *         operations. If it is not null, the operationList object with
25401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa     *         operations inserted by this method.
2541f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa     */
25421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public ArrayList<ContentProviderOperation> constructInsertOperations(ContentResolver resolver,
25431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            ArrayList<ContentProviderOperation> operationList) {
2544f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        if (operationList == null) {
2545f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa            operationList = new ArrayList<ContentProviderOperation>();
2546f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        }
2547f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa
25481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (isIgnorable()) {
254948dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa            return operationList;
255048dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        }
255148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
2552f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        final int backReferenceIndex = operationList.size();
2553f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa
25544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // After applying the batch the first result's Uri is returned so it is important that
2555f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        // the RawContact is the first operation that gets inserted into the list.
25561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        ContentProviderOperation.Builder builder = ContentProviderOperation
25571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                .newInsert(RawContacts.CONTENT_URI);
25584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mAccount != null) {
25594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.withValue(RawContacts.ACCOUNT_NAME, mAccount.name);
25604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.withValue(RawContacts.ACCOUNT_TYPE, mAccount.type);
25614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
25624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.withValue(RawContacts.ACCOUNT_NAME, null);
25634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.withValue(RawContacts.ACCOUNT_TYPE, null);
25644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
25654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        operationList.add(builder.build());
25664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
25671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        int start = operationList.size();
25681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        iterateAllData(new InsertOperationConstrutor(operationList, backReferenceIndex));
25691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        int end = operationList.size();
25704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
2571f98084b727f30713a31ace82e63341a4fa2ae5d7Daisuke Miyakawa        return operationList;
25724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
25734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
25744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public static VCardEntry buildFromResolver(ContentResolver resolver) {
25754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return buildFromResolver(resolver, Contacts.CONTENT_URI);
25764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
25774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
25784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public static VCardEntry buildFromResolver(ContentResolver resolver, Uri uri) {
25794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return null;
25804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
25814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
25821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private String listToString(List<String> list) {
25834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        final int size = list.size();
25844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (size > 1) {
25854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            StringBuilder builder = new StringBuilder();
25864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            int i = 0;
25874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            for (String type : list) {
25884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                builder.append(type);
25894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (i < size - 1) {
25904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    builder.append(";");
25914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
25924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
25934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return builder.toString();
25944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (size == 1) {
25954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return list.get(0);
25964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
25974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return "";
25984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
25994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public final NameData getNameData() {
26021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mNameData;
26034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public final List<NicknameData> getNickNameList() {
26061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mNicknameList;
26074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public final String getBirthday() {
26101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mBirthday != null ? mBirthday.mBirthday : null;
26114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public final List<NoteData> getNotes() {
26144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mNoteList;
26154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public final List<PhoneData> getPhoneList() {
26184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mPhoneList;
26194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public final List<EmailData> getEmailList() {
26224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mEmailList;
26234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public final List<PostalData> getPostalList() {
26264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mPostalList;
26274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public final List<OrganizationData> getOrganizationList() {
26304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mOrganizationList;
26314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public final List<ImData> getImList() {
26344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mImList;
26354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public final List<PhotoData> getPhotoList() {
26384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mPhotoList;
26394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
26411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public final List<WebsiteData> getWebsiteList() {
26424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return mWebsiteList;
26434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
26444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
264548dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    /**
264648dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa     * @hide this interface may be changed for better support of vCard 4.0 (UID)
264748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa     */
264848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    public final List<VCardEntry> getChildlen() {
264948dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        return mChildren;
265048dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    }
265148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
26524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public String getDisplayName() {
26531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mNameData.displayName == null) {
26541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mNameData.displayName = constructDisplayName();
26554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
26561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mNameData.displayName;
26574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
2658600d08e46f52d510598ffe382bf83f576f7ab8a6Rakesh Iyer
2659600d08e46f52d510598ffe382bf83f576f7ab8a6Rakesh Iyer    public List<Pair<String, String>> getUnknownXData() {
2660600d08e46f52d510598ffe382bf83f576f7ab8a6Rakesh Iyer        return mUnknownXData;
2661600d08e46f52d510598ffe382bf83f576f7ab8a6Rakesh Iyer    }
26624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa}
2663