/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.vcard;

import com.android.vcard.VCardUtils.PhoneNumberUtilsPort;

import android.accounts.Account;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.provider.ContactsContract.CommonDataKinds.Note;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.SipAddress;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Represents one vCard entry, which should start with "BEGIN:VCARD" and end
 * with "END:VCARD". This class is for bridging between real vCard data and
 * Android's {@link ContactsContract}, which means some aspects of vCard are
 * dropped before this object being constructed. Raw vCard data should be first
 * supplied with {@link #addProperty(VCardProperty)}. After supplying all data,
 * user should call {@link #consolidateFields()} to prepare some additional
 * information which is constructable from supplied raw data. TODO: preserve raw
 * data using {@link VCardProperty}. If it may just waste memory, this at least
 * should contain them when it cannot convert vCard as a string to Android's
 * Contacts representation. Those raw properties should _not_ be used for
 * {@link #isIgnorable()}.
 */
public class VCardEntry {
    private static final String LOG_TAG = VCardConstants.LOG_TAG;

    private static final int DEFAULT_ORGANIZATION_TYPE = Organization.TYPE_WORK;

    private static final Map<String, Integer> sImMap = new HashMap<String, Integer>();

    static {
        sImMap.put(VCardConstants.PROPERTY_X_AIM, Im.PROTOCOL_AIM);
        sImMap.put(VCardConstants.PROPERTY_X_MSN, Im.PROTOCOL_MSN);
        sImMap.put(VCardConstants.PROPERTY_X_YAHOO, Im.PROTOCOL_YAHOO);
        sImMap.put(VCardConstants.PROPERTY_X_ICQ, Im.PROTOCOL_ICQ);
        sImMap.put(VCardConstants.PROPERTY_X_JABBER, Im.PROTOCOL_JABBER);
        sImMap.put(VCardConstants.PROPERTY_X_SKYPE_USERNAME, Im.PROTOCOL_SKYPE);
        sImMap.put(VCardConstants.PROPERTY_X_GOOGLE_TALK, Im.PROTOCOL_GOOGLE_TALK);
        sImMap.put(VCardConstants.ImportOnly.PROPERTY_X_GOOGLE_TALK_WITH_SPACE,
                Im.PROTOCOL_GOOGLE_TALK);
    }

    /**
     * Whether to insert this VCardEntry as RawContacts.STARRED
     */
    private boolean mStarred = false;

    public void setStarred(boolean val) {
        mStarred = val;
    }
    public boolean getStarred() {
        return mStarred;
    }

    public enum EntryLabel {
        NAME,
        PHONE,
        EMAIL,
        POSTAL_ADDRESS,
        ORGANIZATION,
        IM,
        PHOTO,
        WEBSITE,
        SIP,
        NICKNAME,
        NOTE,
        BIRTHDAY,
        ANNIVERSARY,
        ANDROID_CUSTOM
    }

    public static interface EntryElement {
        // Also need to inherit toString(), equals().
        public EntryLabel getEntryLabel();

        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex);

        public boolean isEmpty();
    }

    // TODO: vCard 4.0 logically has multiple formatted names and we need to
    // select the most preferable one using PREF parameter.
    //
    // e.g. (based on rev.13)
    // FN;PREF=1:John M. Doe
    // FN;PREF=2:John Doe
    // FN;PREF=3;John
    public static class NameData implements EntryElement {
        private String mFamily;
        private String mGiven;
        private String mMiddle;
        private String mPrefix;
        private String mSuffix;

        // Used only when no family nor given name is found.
        private String mFormatted;

        private String mPhoneticFamily;
        private String mPhoneticGiven;
        private String mPhoneticMiddle;

        // For "SORT-STRING" in vCard 3.0.
        private String mSortString;

        /**
         * Not in vCard but for {@link StructuredName#DISPLAY_NAME}. This field
         * is constructed by VCardEntry on demand. Consider using
         * {@link VCardEntry#getDisplayName()}.
         */
        // This field should reflect the other Elem fields like Email,
        // PostalAddress, etc., while
        // This is static class which cannot see other data. Thus we ask
        // VCardEntry to populate it.
        public String displayName;

        public boolean emptyStructuredName() {
            return TextUtils.isEmpty(mFamily) && TextUtils.isEmpty(mGiven)
                    && TextUtils.isEmpty(mMiddle) && TextUtils.isEmpty(mPrefix)
                    && TextUtils.isEmpty(mSuffix);
        }

        public boolean emptyPhoneticStructuredName() {
            return TextUtils.isEmpty(mPhoneticFamily) && TextUtils.isEmpty(mPhoneticGiven)
                    && TextUtils.isEmpty(mPhoneticMiddle);
        }

        @Override
        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            final ContentProviderOperation.Builder builder = ContentProviderOperation
                    .newInsert(Data.CONTENT_URI);
            builder.withValueBackReference(StructuredName.RAW_CONTACT_ID, backReferenceIndex);
            builder.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);

            if (!TextUtils.isEmpty(mGiven)) {
                builder.withValue(StructuredName.GIVEN_NAME, mGiven);
            }
            if (!TextUtils.isEmpty(mFamily)) {
                builder.withValue(StructuredName.FAMILY_NAME, mFamily);
            }
            if (!TextUtils.isEmpty(mMiddle)) {
                builder.withValue(StructuredName.MIDDLE_NAME, mMiddle);
            }
            if (!TextUtils.isEmpty(mPrefix)) {
                builder.withValue(StructuredName.PREFIX, mPrefix);
            }
            if (!TextUtils.isEmpty(mSuffix)) {
                builder.withValue(StructuredName.SUFFIX, mSuffix);
            }

            boolean phoneticNameSpecified = false;

            if (!TextUtils.isEmpty(mPhoneticGiven)) {
                builder.withValue(StructuredName.PHONETIC_GIVEN_NAME, mPhoneticGiven);
                phoneticNameSpecified = true;
            }
            if (!TextUtils.isEmpty(mPhoneticFamily)) {
                builder.withValue(StructuredName.PHONETIC_FAMILY_NAME, mPhoneticFamily);
                phoneticNameSpecified = true;
            }
            if (!TextUtils.isEmpty(mPhoneticMiddle)) {
                builder.withValue(StructuredName.PHONETIC_MIDDLE_NAME, mPhoneticMiddle);
                phoneticNameSpecified = true;
            }

            // SORT-STRING is used only when phonetic names aren't specified in
            // the original vCard.
            if (!phoneticNameSpecified) {
                builder.withValue(StructuredName.PHONETIC_GIVEN_NAME, mSortString);
            }

            builder.withValue(StructuredName.DISPLAY_NAME, displayName);
            operationList.add(builder.build());
        }

        @Override
        public boolean isEmpty() {
            return (TextUtils.isEmpty(mFamily) && TextUtils.isEmpty(mMiddle)
                    && TextUtils.isEmpty(mGiven) && TextUtils.isEmpty(mPrefix)
                    && TextUtils.isEmpty(mSuffix) && TextUtils.isEmpty(mFormatted)
                    && TextUtils.isEmpty(mPhoneticFamily) && TextUtils.isEmpty(mPhoneticMiddle)
                    && TextUtils.isEmpty(mPhoneticGiven) && TextUtils.isEmpty(mSortString));
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof NameData)) {
                return false;
            }
            NameData nameData = (NameData) obj;

            return (TextUtils.equals(mFamily, nameData.mFamily)
                    && TextUtils.equals(mMiddle, nameData.mMiddle)
                    && TextUtils.equals(mGiven, nameData.mGiven)
                    && TextUtils.equals(mPrefix, nameData.mPrefix)
                    && TextUtils.equals(mSuffix, nameData.mSuffix)
                    && TextUtils.equals(mFormatted, nameData.mFormatted)
                    && TextUtils.equals(mPhoneticFamily, nameData.mPhoneticFamily)
                    && TextUtils.equals(mPhoneticMiddle, nameData.mPhoneticMiddle)
                    && TextUtils.equals(mPhoneticGiven, nameData.mPhoneticGiven)
                    && TextUtils.equals(mSortString, nameData.mSortString));
        }

        @Override
        public int hashCode() {
            final String[] hashTargets = new String[] {mFamily, mMiddle, mGiven, mPrefix, mSuffix,
                    mFormatted, mPhoneticFamily, mPhoneticMiddle,
                    mPhoneticGiven, mSortString};
            int hash = 0;
            for (String hashTarget : hashTargets) {
                hash = hash * 31 + (hashTarget != null ? hashTarget.hashCode() : 0);
            }
            return hash;
        }

        @Override
        public String toString() {
            return String.format("family: %s, given: %s, middle: %s, prefix: %s, suffix: %s",
                    mFamily, mGiven, mMiddle, mPrefix, mSuffix);
        }

        @Override
        public final EntryLabel getEntryLabel() {
            return EntryLabel.NAME;
        }

        public String getFamily() {
            return mFamily;
        }

        public String getMiddle() {
            return mMiddle;
        }

        public String getGiven() {
            return mGiven;
        }

        public String getPrefix() {
            return mPrefix;
        }

        public String getSuffix() {
            return mSuffix;
        }

        public String getFormatted() {
            return mFormatted;
        }

        public String getSortString() {
            return mSortString;
        }

        /** @hide Just for testing. */
        public void setFamily(String family) { mFamily = family; }
        /** @hide Just for testing. */
        public void setMiddle(String middle) { mMiddle = middle; }
        /** @hide Just for testing. */
        public void setGiven(String given) { mGiven = given; }
        /** @hide Just for testing. */
        public void setPrefix(String prefix) { mPrefix = prefix; }
        /** @hide Just for testing. */
        public void setSuffix(String suffix) { mSuffix = suffix; }
    }

    public static class PhoneData implements EntryElement {
        private final String mNumber;
        private final int mType;
        private final String mLabel;

        // isPrimary is (not final but) changable, only when there's no
        // appropriate one existing
        // in the original VCard.
        private boolean mIsPrimary;

        public PhoneData(String data, int type, String label, boolean isPrimary) {
            mNumber = data;
            mType = type;
            mLabel = label;
            mIsPrimary = isPrimary;
        }

        @Override
        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            final ContentProviderOperation.Builder builder = ContentProviderOperation
                    .newInsert(Data.CONTENT_URI);
            builder.withValueBackReference(Phone.RAW_CONTACT_ID, backReferenceIndex);
            builder.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);

            builder.withValue(Phone.TYPE, mType);
            if (mType == Phone.TYPE_CUSTOM) {
                builder.withValue(Phone.LABEL, mLabel);
            }
            builder.withValue(Phone.NUMBER, mNumber);
            if (mIsPrimary) {
                builder.withValue(Phone.IS_PRIMARY, 1);
            }
            operationList.add(builder.build());
        }

        @Override
        public boolean isEmpty() {
            return TextUtils.isEmpty(mNumber);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof PhoneData)) {
                return false;
            }
            PhoneData phoneData = (PhoneData) obj;
            return (mType == phoneData.mType
                    && TextUtils.equals(mNumber, phoneData.mNumber)
                    && TextUtils.equals(mLabel, phoneData.mLabel)
                    && (mIsPrimary == phoneData.mIsPrimary));
        }

        @Override
        public int hashCode() {
            int hash = mType;
            hash = hash * 31 + (mNumber != null ? mNumber.hashCode() : 0);
            hash = hash * 31 + (mLabel != null ? mLabel.hashCode() : 0);
            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
            return hash;
        }

        @Override
        public String toString() {
            return String.format("type: %d, data: %s, label: %s, isPrimary: %s", mType, mNumber,
                    mLabel, mIsPrimary);
        }

        @Override
        public final EntryLabel getEntryLabel() {
            return EntryLabel.PHONE;
        }

        public String getNumber() {
            return mNumber;
        }

        public int getType() {
            return mType;
        }

        public String getLabel() {
            return mLabel;
        }

        public boolean isPrimary() {
            return mIsPrimary;
        }
    }

    public static class EmailData implements EntryElement {
        private final String mAddress;
        private final int mType;
        // Used only when TYPE is TYPE_CUSTOM.
        private final String mLabel;
        private final boolean mIsPrimary;

        public EmailData(String data, int type, String label, boolean isPrimary) {
            mType = type;
            mAddress = data;
            mLabel = label;
            mIsPrimary = isPrimary;
        }

        @Override
        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            final ContentProviderOperation.Builder builder = ContentProviderOperation
                    .newInsert(Data.CONTENT_URI);
            builder.withValueBackReference(Email.RAW_CONTACT_ID, backReferenceIndex);
            builder.withValue(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);

            builder.withValue(Email.TYPE, mType);
            if (mType == Email.TYPE_CUSTOM) {
                builder.withValue(Email.LABEL, mLabel);
            }
            builder.withValue(Email.DATA, mAddress);
            if (mIsPrimary) {
                builder.withValue(Data.IS_PRIMARY, 1);
            }
            operationList.add(builder.build());
        }

        @Override
        public boolean isEmpty() {
            return TextUtils.isEmpty(mAddress);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof EmailData)) {
                return false;
            }
            EmailData emailData = (EmailData) obj;
            return (mType == emailData.mType
                    && TextUtils.equals(mAddress, emailData.mAddress)
                    && TextUtils.equals(mLabel, emailData.mLabel)
                    && (mIsPrimary == emailData.mIsPrimary));
        }

        @Override
        public int hashCode() {
            int hash = mType;
            hash = hash * 31 + (mAddress != null ? mAddress.hashCode() : 0);
            hash = hash * 31 + (mLabel != null ? mLabel.hashCode() : 0);
            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
            return hash;
        }

        @Override
        public String toString() {
            return String.format("type: %d, data: %s, label: %s, isPrimary: %s", mType, mAddress,
                    mLabel, mIsPrimary);
        }

        @Override
        public final EntryLabel getEntryLabel() {
            return EntryLabel.EMAIL;
        }

        public String getAddress() {
            return mAddress;
        }

        public int getType() {
            return mType;
        }

        public String getLabel() {
            return mLabel;
        }

        public boolean isPrimary() {
            return mIsPrimary;
        }
    }

    public static class PostalData implements EntryElement {
        // Determined by vCard specification.
        // - PO Box, Extended Addr, Street, Locality, Region, Postal Code, Country Name
        private static final int ADDR_MAX_DATA_SIZE = 7;
        private final String mPobox;
        private final String mExtendedAddress;
        private final String mStreet;
        private final String mLocalty;
        private final String mRegion;
        private final String mPostalCode;
        private final String mCountry;
        private final int mType;
        private final String mLabel;
        private boolean mIsPrimary;

        /** We keep this for {@link StructuredPostal#FORMATTED_ADDRESS} */
        // TODO: need better way to construct formatted address.
        private int mVCardType;

        public PostalData(String pobox, String extendedAddress, String street, String localty,
                String region, String postalCode, String country, int type, String label,
                boolean isPrimary, int vcardType) {
            mType = type;
            mPobox = pobox;
            mExtendedAddress = extendedAddress;
            mStreet = street;
            mLocalty = localty;
            mRegion = region;
            mPostalCode = postalCode;
            mCountry = country;
            mLabel = label;
            mIsPrimary = isPrimary;
            mVCardType = vcardType;
        }

        /**
         * Accepts raw propertyValueList in vCard and constructs PostalData.
         */
        public static PostalData constructPostalData(final List<String> propValueList,
                final int type, final String label, boolean isPrimary, int vcardType) {
            final String[] dataArray = new String[ADDR_MAX_DATA_SIZE];

            int size = propValueList.size();
            if (size > ADDR_MAX_DATA_SIZE) {
                size = ADDR_MAX_DATA_SIZE;
            }

            // adr-value = 0*6(text-value ";") text-value
            // ; PO Box, Extended Address, Street, Locality, Region, Postal Code, Country Name
            //
            // Use Iterator assuming List may be LinkedList, though actually it is
            // always ArrayList in the current implementation.
            int i = 0;
            for (String addressElement : propValueList) {
                dataArray[i] = addressElement;
                if (++i >= size) {
                    break;
                }
            }
            while (i < ADDR_MAX_DATA_SIZE) {
                dataArray[i++] = null;
            }

            return new PostalData(dataArray[0], dataArray[1], dataArray[2], dataArray[3],
                    dataArray[4], dataArray[5], dataArray[6], type, label, isPrimary, vcardType);
        }

        @Override
        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            final ContentProviderOperation.Builder builder = ContentProviderOperation
                    .newInsert(Data.CONTENT_URI);
            builder.withValueBackReference(StructuredPostal.RAW_CONTACT_ID, backReferenceIndex);
            builder.withValue(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE);

            builder.withValue(StructuredPostal.TYPE, mType);
            if (mType == StructuredPostal.TYPE_CUSTOM) {
                builder.withValue(StructuredPostal.LABEL, mLabel);
            }

            final String streetString;
            if (TextUtils.isEmpty(mStreet)) {
                if (TextUtils.isEmpty(mExtendedAddress)) {
                    streetString = null;
                } else {
                    streetString = mExtendedAddress;
                }
            } else {
                if (TextUtils.isEmpty(mExtendedAddress)) {
                    streetString = mStreet;
                } else {
                    streetString = mStreet + " " + mExtendedAddress;
                }
            }
            builder.withValue(StructuredPostal.POBOX, mPobox);
            builder.withValue(StructuredPostal.STREET, streetString);
            builder.withValue(StructuredPostal.CITY, mLocalty);
            builder.withValue(StructuredPostal.REGION, mRegion);
            builder.withValue(StructuredPostal.POSTCODE, mPostalCode);
            builder.withValue(StructuredPostal.COUNTRY, mCountry);

            builder.withValue(StructuredPostal.FORMATTED_ADDRESS, getFormattedAddress(mVCardType));
            if (mIsPrimary) {
                builder.withValue(Data.IS_PRIMARY, 1);
            }
            operationList.add(builder.build());
        }

        public String getFormattedAddress(final int vcardType) {
            StringBuilder builder = new StringBuilder();
            boolean empty = true;
            final String[] dataArray = new String[] {
                    mPobox, mExtendedAddress, mStreet, mLocalty, mRegion, mPostalCode, mCountry
            };
            if (VCardConfig.isJapaneseDevice(vcardType)) {
                // In Japan, the order is reversed.
                for (int i = ADDR_MAX_DATA_SIZE - 1; i >= 0; i--) {
                    String addressPart = dataArray[i];
                    if (!TextUtils.isEmpty(addressPart)) {
                        if (!empty) {
                            builder.append(' ');
                        } else {
                            empty = false;
                        }
                        builder.append(addressPart);
                    }
                }
            } else {
                for (int i = 0; i < ADDR_MAX_DATA_SIZE; i++) {
                    String addressPart = dataArray[i];
                    if (!TextUtils.isEmpty(addressPart)) {
                        if (!empty) {
                            builder.append(' ');
                        } else {
                            empty = false;
                        }
                        builder.append(addressPart);
                    }
                }
            }

            return builder.toString().trim();
        }

        @Override
        public boolean isEmpty() {
            return (TextUtils.isEmpty(mPobox)
                    && TextUtils.isEmpty(mExtendedAddress)
                    && TextUtils.isEmpty(mStreet)
                    && TextUtils.isEmpty(mLocalty)
                    && TextUtils.isEmpty(mRegion)
                    && TextUtils.isEmpty(mPostalCode)
                    && TextUtils.isEmpty(mCountry));
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof PostalData)) {
                return false;
            }
            final PostalData postalData = (PostalData) obj;
            return (mType == postalData.mType)
                    && (mType == StructuredPostal.TYPE_CUSTOM ? TextUtils.equals(mLabel,
                            postalData.mLabel) : true)
                    && (mIsPrimary == postalData.mIsPrimary)
                    && TextUtils.equals(mPobox, postalData.mPobox)
                    && TextUtils.equals(mExtendedAddress, postalData.mExtendedAddress)
                    && TextUtils.equals(mStreet, postalData.mStreet)
                    && TextUtils.equals(mLocalty, postalData.mLocalty)
                    && TextUtils.equals(mRegion, postalData.mRegion)
                    && TextUtils.equals(mPostalCode, postalData.mPostalCode)
                    && TextUtils.equals(mCountry, postalData.mCountry);
        }

        @Override
        public int hashCode() {
            int hash = mType;
            hash = hash * 31 + (mLabel != null ? mLabel.hashCode() : 0);
            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);

            final String[] hashTargets = new String[] {mPobox, mExtendedAddress, mStreet,
                    mLocalty, mRegion, mPostalCode, mCountry};
            for (String hashTarget : hashTargets) {
                hash = hash * 31 + (hashTarget != null ? hashTarget.hashCode() : 0);
            }
            return hash;
        }

        @Override
        public String toString() {
            return String.format("type: %d, label: %s, isPrimary: %s, pobox: %s, "
                    + "extendedAddress: %s, street: %s, localty: %s, region: %s, postalCode %s, "
                    + "country: %s", mType, mLabel, mIsPrimary, mPobox, mExtendedAddress, mStreet,
                    mLocalty, mRegion, mPostalCode, mCountry);
        }

        @Override
        public final EntryLabel getEntryLabel() {
            return EntryLabel.POSTAL_ADDRESS;
        }

        public String getPobox() {
            return mPobox;
        }

        public String getExtendedAddress() {
            return mExtendedAddress;
        }

        public String getStreet() {
            return mStreet;
        }

        public String getLocalty() {
            return mLocalty;
        }

        public String getRegion() {
            return mRegion;
        }

        public String getPostalCode() {
            return mPostalCode;
        }

        public String getCountry() {
            return mCountry;
        }

        public int getType() {
            return mType;
        }

        public String getLabel() {
            return mLabel;
        }

        public boolean isPrimary() {
            return mIsPrimary;
        }
    }

    public static class OrganizationData implements EntryElement {
        // non-final is Intentional: we may change the values since this info is separated into
        // two parts in vCard: "ORG" + "TITLE", and we have to cope with each field in different
        // timing.
        private String mOrganizationName;
        private String mDepartmentName;
        private String mTitle;
        private final String mPhoneticName; // We won't have this in "TITLE" property.
        private final int mType;
        private boolean mIsPrimary;

        public OrganizationData(final String organizationName, final String departmentName,
                final String titleName, final String phoneticName, int type,
                final boolean isPrimary) {
            mType = type;
            mOrganizationName = organizationName;
            mDepartmentName = departmentName;
            mTitle = titleName;
            mPhoneticName = phoneticName;
            mIsPrimary = isPrimary;
        }

        public String getFormattedString() {
            final StringBuilder builder = new StringBuilder();
            if (!TextUtils.isEmpty(mOrganizationName)) {
                builder.append(mOrganizationName);
            }

            if (!TextUtils.isEmpty(mDepartmentName)) {
                if (builder.length() > 0) {
                    builder.append(", ");
                }
                builder.append(mDepartmentName);
            }

            if (!TextUtils.isEmpty(mTitle)) {
                if (builder.length() > 0) {
                    builder.append(", ");
                }
                builder.append(mTitle);
            }

            return builder.toString();
        }

        @Override
        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            final ContentProviderOperation.Builder builder = ContentProviderOperation
                    .newInsert(Data.CONTENT_URI);
            builder.withValueBackReference(Organization.RAW_CONTACT_ID, backReferenceIndex);
            builder.withValue(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
            builder.withValue(Organization.TYPE, mType);
            if (mOrganizationName != null) {
                builder.withValue(Organization.COMPANY, mOrganizationName);
            }
            if (mDepartmentName != null) {
                builder.withValue(Organization.DEPARTMENT, mDepartmentName);
            }
            if (mTitle != null) {
                builder.withValue(Organization.TITLE, mTitle);
            }
            if (mPhoneticName != null) {
                builder.withValue(Organization.PHONETIC_NAME, mPhoneticName);
            }
            if (mIsPrimary) {
                builder.withValue(Organization.IS_PRIMARY, 1);
            }
            operationList.add(builder.build());
        }

        @Override
        public boolean isEmpty() {
            return TextUtils.isEmpty(mOrganizationName) && TextUtils.isEmpty(mDepartmentName)
                    && TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mPhoneticName);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof OrganizationData)) {
                return false;
            }
            OrganizationData organization = (OrganizationData) obj;
            return (mType == organization.mType
                    && TextUtils.equals(mOrganizationName, organization.mOrganizationName)
                    && TextUtils.equals(mDepartmentName, organization.mDepartmentName)
                    && TextUtils.equals(mTitle, organization.mTitle)
                    && (mIsPrimary == organization.mIsPrimary));
        }

        @Override
        public int hashCode() {
            int hash = mType;
            hash = hash * 31 + (mOrganizationName != null ? mOrganizationName.hashCode() : 0);
            hash = hash * 31 + (mDepartmentName != null ? mDepartmentName.hashCode() : 0);
            hash = hash * 31 + (mTitle != null ? mTitle.hashCode() : 0);
            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
            return hash;
        }

        @Override
        public String toString() {
            return String.format(
                    "type: %d, organization: %s, department: %s, title: %s, isPrimary: %s", mType,
                    mOrganizationName, mDepartmentName, mTitle, mIsPrimary);
        }

        @Override
        public final EntryLabel getEntryLabel() {
            return EntryLabel.ORGANIZATION;
        }

        public String getOrganizationName() {
            return mOrganizationName;
        }

        public String getDepartmentName() {
            return mDepartmentName;
        }

        public String getTitle() {
            return mTitle;
        }

        public String getPhoneticName() {
            return mPhoneticName;
        }

        public int getType() {
            return mType;
        }

        public boolean isPrimary() {
            return mIsPrimary;
        }
    }

    public static class ImData implements EntryElement {
        private final String mAddress;
        private final int mProtocol;
        private final String mCustomProtocol;
        private final int mType;
        private final boolean mIsPrimary;

        public ImData(final int protocol, final String customProtocol, final String address,
                final int type, final boolean isPrimary) {
            mProtocol = protocol;
            mCustomProtocol = customProtocol;
            mType = type;
            mAddress = address;
            mIsPrimary = isPrimary;
        }

        @Override
        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            final ContentProviderOperation.Builder builder = ContentProviderOperation
                    .newInsert(Data.CONTENT_URI);
            builder.withValueBackReference(Im.RAW_CONTACT_ID, backReferenceIndex);
            builder.withValue(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
            builder.withValue(Im.TYPE, mType);
            builder.withValue(Im.PROTOCOL, mProtocol);
            builder.withValue(Im.DATA, mAddress);
            if (mProtocol == Im.PROTOCOL_CUSTOM) {
                builder.withValue(Im.CUSTOM_PROTOCOL, mCustomProtocol);
            }
            if (mIsPrimary) {
                builder.withValue(Data.IS_PRIMARY, 1);
            }
            operationList.add(builder.build());
        }

        @Override
        public boolean isEmpty() {
            return TextUtils.isEmpty(mAddress);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof ImData)) {
                return false;
            }
            ImData imData = (ImData) obj;
            return (mType == imData.mType
                    && mProtocol == imData.mProtocol
                    && TextUtils.equals(mCustomProtocol, imData.mCustomProtocol)
                    && TextUtils.equals(mAddress, imData.mAddress)
                    && (mIsPrimary == imData.mIsPrimary));
        }

        @Override
        public int hashCode() {
            int hash = mType;
            hash = hash * 31 + mProtocol;
            hash = hash * 31 + (mCustomProtocol != null ? mCustomProtocol.hashCode() : 0);
            hash = hash * 31 + (mAddress != null ? mAddress.hashCode() : 0);
            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
            return hash;
        }

        @Override
        public String toString() {
            return String.format(
                    "type: %d, protocol: %d, custom_protcol: %s, data: %s, isPrimary: %s", mType,
                    mProtocol, mCustomProtocol, mAddress, mIsPrimary);
        }

        @Override
        public final EntryLabel getEntryLabel() {
            return EntryLabel.IM;
        }

        public String getAddress() {
            return mAddress;
        }

        /**
         * One of the value available for {@link Im#PROTOCOL}. e.g.
         * {@link Im#PROTOCOL_GOOGLE_TALK}
         */
        public int getProtocol() {
            return mProtocol;
        }

        public String getCustomProtocol() {
            return mCustomProtocol;
        }

        public int getType() {
            return mType;
        }

        public boolean isPrimary() {
            return mIsPrimary;
        }
    }

    public static class PhotoData implements EntryElement {
        // private static final String FORMAT_FLASH = "SWF";

        // used when type is not defined in ContactsContract.
        private final String mFormat;
        private final boolean mIsPrimary;

        private final byte[] mBytes;

        private Integer mHashCode = null;

        public PhotoData(String format, byte[] photoBytes, boolean isPrimary) {
            mFormat = format;
            mBytes = photoBytes;
            mIsPrimary = isPrimary;
        }

        @Override
        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            final ContentProviderOperation.Builder builder = ContentProviderOperation
                    .newInsert(Data.CONTENT_URI);
            builder.withValueBackReference(Photo.RAW_CONTACT_ID, backReferenceIndex);
            builder.withValue(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE);
            builder.withValue(Photo.PHOTO, mBytes);
            if (mIsPrimary) {
                builder.withValue(Photo.IS_PRIMARY, 1);
            }
            operationList.add(builder.build());
        }

        @Override
        public boolean isEmpty() {
            return mBytes == null || mBytes.length == 0;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof PhotoData)) {
                return false;
            }
            PhotoData photoData = (PhotoData) obj;
            return (TextUtils.equals(mFormat, photoData.mFormat)
                    && Arrays.equals(mBytes, photoData.mBytes)
                    && (mIsPrimary == photoData.mIsPrimary));
        }

        @Override
        public int hashCode() {
            if (mHashCode != null) {
                return mHashCode;
            }

            int hash = mFormat != null ? mFormat.hashCode() : 0;
            hash = hash * 31;
            if (mBytes != null) {
                for (byte b : mBytes) {
                    hash += b;
                }
            }

            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
            mHashCode = hash;
            return hash;
        }

        @Override
        public String toString() {
            return String.format("format: %s: size: %d, isPrimary: %s", mFormat, mBytes.length,
                    mIsPrimary);
        }

        @Override
        public final EntryLabel getEntryLabel() {
            return EntryLabel.PHOTO;
        }

        public String getFormat() {
            return mFormat;
        }

        public byte[] getBytes() {
            return mBytes;
        }

        public boolean isPrimary() {
            return mIsPrimary;
        }
    }

    public static class NicknameData implements EntryElement {
        private final String mNickname;

        public NicknameData(String nickname) {
            mNickname = nickname;
        }

        @Override
        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            final ContentProviderOperation.Builder builder = ContentProviderOperation
                    .newInsert(Data.CONTENT_URI);
            builder.withValueBackReference(Nickname.RAW_CONTACT_ID, backReferenceIndex);
            builder.withValue(Data.MIMETYPE, Nickname.CONTENT_ITEM_TYPE);
            builder.withValue(Nickname.TYPE, Nickname.TYPE_DEFAULT);
            builder.withValue(Nickname.NAME, mNickname);
            operationList.add(builder.build());
        }

        @Override
        public boolean isEmpty() {
            return TextUtils.isEmpty(mNickname);
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof NicknameData)) {
                return false;
            }
            NicknameData nicknameData = (NicknameData) obj;
            return TextUtils.equals(mNickname, nicknameData.mNickname);
        }

        @Override
        public int hashCode() {
            return mNickname != null ? mNickname.hashCode() : 0;
        }

        @Override
        public String toString() {
            return "nickname: " + mNickname;
        }

        @Override
        public EntryLabel getEntryLabel() {
            return EntryLabel.NICKNAME;
        }

        public String getNickname() {
            return mNickname;
        }
    }

    public static class NoteData implements EntryElement {
        public final String mNote;

        public NoteData(String note) {
            mNote = note;
        }

        @Override
        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            final ContentProviderOperation.Builder builder = ContentProviderOperation
                    .newInsert(Data.CONTENT_URI);
            builder.withValueBackReference(Note.RAW_CONTACT_ID, backReferenceIndex);
            builder.withValue(Data.MIMETYPE, Note.CONTENT_ITEM_TYPE);
            builder.withValue(Note.NOTE, mNote);
            operationList.add(builder.build());
        }

        @Override
        public boolean isEmpty() {
            return TextUtils.isEmpty(mNote);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof NoteData)) {
                return false;
            }
            NoteData noteData = (NoteData) obj;
            return TextUtils.equals(mNote, noteData.mNote);
        }

        @Override
        public int hashCode() {
            return mNote != null ? mNote.hashCode() : 0;
        }

        @Override
        public String toString() {
            return "note: " + mNote;
        }

        @Override
        public EntryLabel getEntryLabel() {
            return EntryLabel.NOTE;
        }

        public String getNote() {
            return mNote;
        }
    }

    public static class WebsiteData implements EntryElement {
        private final String mWebsite;

        public WebsiteData(String website) {
            mWebsite = website;
        }

        @Override
        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            final ContentProviderOperation.Builder builder = ContentProviderOperation
                    .newInsert(Data.CONTENT_URI);
            builder.withValueBackReference(Website.RAW_CONTACT_ID, backReferenceIndex);
            builder.withValue(Data.MIMETYPE, Website.CONTENT_ITEM_TYPE);
            builder.withValue(Website.URL, mWebsite);
            // There's no information about the type of URL in vCard.
            // We use TYPE_HOMEPAGE for safety.
            builder.withValue(Website.TYPE, Website.TYPE_HOMEPAGE);
            operationList.add(builder.build());
        }

        @Override
        public boolean isEmpty() {
            return TextUtils.isEmpty(mWebsite);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof WebsiteData)) {
                return false;
            }
            WebsiteData websiteData = (WebsiteData) obj;
            return TextUtils.equals(mWebsite, websiteData.mWebsite);
        }

        @Override
        public int hashCode() {
            return mWebsite != null ? mWebsite.hashCode() : 0;
        }

        @Override
        public String toString() {
            return "website: " + mWebsite;
        }

        @Override
        public EntryLabel getEntryLabel() {
            return EntryLabel.WEBSITE;
        }

        public String getWebsite() {
            return mWebsite;
        }
    }

    public static class BirthdayData implements EntryElement {
        private final String mBirthday;

        public BirthdayData(String birthday) {
            mBirthday = birthday;
        }

        @Override
        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            final ContentProviderOperation.Builder builder = ContentProviderOperation
                    .newInsert(Data.CONTENT_URI);
            builder.withValueBackReference(Event.RAW_CONTACT_ID, backReferenceIndex);
            builder.withValue(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
            builder.withValue(Event.START_DATE, mBirthday);
            builder.withValue(Event.TYPE, Event.TYPE_BIRTHDAY);
            operationList.add(builder.build());
        }

        @Override
        public boolean isEmpty() {
            return TextUtils.isEmpty(mBirthday);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof BirthdayData)) {
                return false;
            }
            BirthdayData birthdayData = (BirthdayData) obj;
            return TextUtils.equals(mBirthday, birthdayData.mBirthday);
        }

        @Override
        public int hashCode() {
            return mBirthday != null ? mBirthday.hashCode() : 0;
        }

        @Override
        public String toString() {
            return "birthday: " + mBirthday;
        }

        @Override
        public EntryLabel getEntryLabel() {
            return EntryLabel.BIRTHDAY;
        }

        public String getBirthday() {
            return mBirthday;
        }
    }

    public static class AnniversaryData implements EntryElement {
        private final String mAnniversary;

        public AnniversaryData(String anniversary) {
            mAnniversary = anniversary;
        }

        @Override
        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            final ContentProviderOperation.Builder builder = ContentProviderOperation
                    .newInsert(Data.CONTENT_URI);
            builder.withValueBackReference(Event.RAW_CONTACT_ID, backReferenceIndex);
            builder.withValue(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
            builder.withValue(Event.START_DATE, mAnniversary);
            builder.withValue(Event.TYPE, Event.TYPE_ANNIVERSARY);
            operationList.add(builder.build());
        }

        @Override
        public boolean isEmpty() {
            return TextUtils.isEmpty(mAnniversary);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof AnniversaryData)) {
                return false;
            }
            AnniversaryData anniversaryData = (AnniversaryData) obj;
            return TextUtils.equals(mAnniversary, anniversaryData.mAnniversary);
        }

        @Override
        public int hashCode() {
            return mAnniversary != null ? mAnniversary.hashCode() : 0;
        }

        @Override
        public String toString() {
            return "anniversary: " + mAnniversary;
        }

        @Override
        public EntryLabel getEntryLabel() {
            return EntryLabel.ANNIVERSARY;
        }

        public String getAnniversary() { return mAnniversary; }
    }

    public static class SipData implements EntryElement {
        /**
         * Note that schema part ("sip:") is automatically removed. e.g.
         * "sip:username:password@host:port" becomes
         * "username:password@host:port"
         */
        private final String mAddress;
        private final int mType;
        private final String mLabel;
        private final boolean mIsPrimary;

        public SipData(String rawSip, int type, String label, boolean isPrimary) {
            if (rawSip.startsWith("sip:")) {
                mAddress = rawSip.substring(4);
            } else {
                mAddress = rawSip;
            }
            mType = type;
            mLabel = label;
            mIsPrimary = isPrimary;
        }

        @Override
        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            final ContentProviderOperation.Builder builder = ContentProviderOperation
                    .newInsert(Data.CONTENT_URI);
            builder.withValueBackReference(SipAddress.RAW_CONTACT_ID, backReferenceIndex);
            builder.withValue(Data.MIMETYPE, SipAddress.CONTENT_ITEM_TYPE);
            builder.withValue(SipAddress.SIP_ADDRESS, mAddress);
            builder.withValue(SipAddress.TYPE, mType);
            if (mType == SipAddress.TYPE_CUSTOM) {
                builder.withValue(SipAddress.LABEL, mLabel);
            }
            if (mIsPrimary) {
                builder.withValue(SipAddress.IS_PRIMARY, mIsPrimary);
            }
            operationList.add(builder.build());
        }

        @Override
        public boolean isEmpty() {
            return TextUtils.isEmpty(mAddress);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof SipData)) {
                return false;
            }
            SipData sipData = (SipData) obj;
            return (mType == sipData.mType
                    && TextUtils.equals(mLabel, sipData.mLabel)
                    && TextUtils.equals(mAddress, sipData.mAddress)
                    && (mIsPrimary == sipData.mIsPrimary));
        }

        @Override
        public int hashCode() {
            int hash = mType;
            hash = hash * 31 + (mLabel != null ? mLabel.hashCode() : 0);
            hash = hash * 31 + (mAddress != null ? mAddress.hashCode() : 0);
            hash = hash * 31 + (mIsPrimary ? 1231 : 1237);
            return hash;
        }

        @Override
        public String toString() {
            return "sip: " + mAddress;
        }

        @Override
        public EntryLabel getEntryLabel() {
            return EntryLabel.SIP;
        }

        /**
         * @return Address part of the sip data. The schema ("sip:") isn't contained here.
         */
        public String getAddress() { return mAddress; }
        public int getType() { return mType; }
        public String getLabel() { return mLabel; }
    }

    /**
     * Some Contacts data in Android cannot be converted to vCard
     * representation. VCardEntry preserves those data using this class.
     */
    public static class AndroidCustomData implements EntryElement {
        private final String mMimeType;

        private final List<String> mDataList; // 1 .. VCardConstants.MAX_DATA_COLUMN

        public AndroidCustomData(String mimeType, List<String> dataList) {
            mMimeType = mimeType;
            mDataList = dataList;
        }

        public static AndroidCustomData constructAndroidCustomData(List<String> list) {
            String mimeType;
            List<String> dataList;

            if (list == null) {
                mimeType = null;
                dataList = null;
            } else if (list.size() < 2) {
                mimeType = list.get(0);
                dataList = null;
            } else {
                final int max = (list.size() < VCardConstants.MAX_DATA_COLUMN + 1) ? list.size()
                        : VCardConstants.MAX_DATA_COLUMN + 1;
                mimeType = list.get(0);
                dataList = list.subList(1, max);
            }

            return new AndroidCustomData(mimeType, dataList);
        }

        @Override
        public void constructInsertOperation(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            final ContentProviderOperation.Builder builder = ContentProviderOperation
                    .newInsert(Data.CONTENT_URI);
            builder.withValueBackReference(GroupMembership.RAW_CONTACT_ID, backReferenceIndex);
            builder.withValue(Data.MIMETYPE, mMimeType);
            for (int i = 0; i < mDataList.size(); i++) {
                String value = mDataList.get(i);
                if (!TextUtils.isEmpty(value)) {
                    // 1-origin
                    builder.withValue("data" + (i + 1), value);
                }
            }
            operationList.add(builder.build());
        }

        @Override
        public boolean isEmpty() {
            return TextUtils.isEmpty(mMimeType) || mDataList == null || mDataList.size() == 0;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof AndroidCustomData)) {
                return false;
            }
            AndroidCustomData data = (AndroidCustomData) obj;
            if (!TextUtils.equals(mMimeType, data.mMimeType)) {
                return false;
            }
            if (mDataList == null) {
                return data.mDataList == null;
            } else {
                final int size = mDataList.size();
                if (size != data.mDataList.size()) {
                    return false;
                }
                for (int i = 0; i < size; i++) {
                    if (!TextUtils.equals(mDataList.get(i), data.mDataList.get(i))) {
                        return false;
                    }
                }
                return true;
            }
        }

        @Override
        public int hashCode() {
            int hash = mMimeType != null ? mMimeType.hashCode() : 0;
            if (mDataList != null) {
                for (String data : mDataList) {
                    hash = hash * 31 + (data != null ? data.hashCode() : 0);
                }
            }
            return hash;
        }

        @Override
        public String toString() {
            final StringBuilder builder = new StringBuilder();
            builder.append("android-custom: " + mMimeType + ", data: ");
            builder.append(mDataList == null ? "null" : Arrays.toString(mDataList.toArray()));
            return builder.toString();
        }

        @Override
        public EntryLabel getEntryLabel() {
            return EntryLabel.ANDROID_CUSTOM;
        }

        public String getMimeType() { return mMimeType; }
        public List<String> getDataList() { return mDataList; }
    }

    private final NameData mNameData = new NameData();
    private List<PhoneData> mPhoneList;
    private List<EmailData> mEmailList;
    private List<PostalData> mPostalList;
    private List<OrganizationData> mOrganizationList;
    private List<ImData> mImList;
    private List<PhotoData> mPhotoList;
    private List<WebsiteData> mWebsiteList;
    private List<SipData> mSipList;
    private List<NicknameData> mNicknameList;
    private List<NoteData> mNoteList;
    private List<AndroidCustomData> mAndroidCustomDataList;
    private BirthdayData mBirthday;
    private AnniversaryData mAnniversary;
    private List<Pair<String, String>> mUnknownXData;

    /**
     * Inner iterator interface.
     */
    public interface EntryElementIterator {
        public void onIterationStarted();

        public void onIterationEnded();

        /**
         * Called when there are one or more {@link EntryElement} instances
         * associated with {@link EntryLabel}.
         */
        public void onElementGroupStarted(EntryLabel label);

        /**
         * Called after all {@link EntryElement} instances for
         * {@link EntryLabel} provided on {@link #onElementGroupStarted(EntryLabel)}
         * being processed by {@link #onElement(EntryElement)}
         */
        public void onElementGroupEnded();

        /**
         * @return should be true when child wants to continue the operation.
         *         False otherwise.
         */
        public boolean onElement(EntryElement elem);
    }

    public final void iterateAllData(EntryElementIterator iterator) {
        iterator.onIterationStarted();
        iterator.onElementGroupStarted(mNameData.getEntryLabel());
        iterator.onElement(mNameData);
        iterator.onElementGroupEnded();

        iterateOneList(mPhoneList, iterator);
        iterateOneList(mEmailList, iterator);
        iterateOneList(mPostalList, iterator);
        iterateOneList(mOrganizationList, iterator);
        iterateOneList(mImList, iterator);
        iterateOneList(mPhotoList, iterator);
        iterateOneList(mWebsiteList, iterator);
        iterateOneList(mSipList, iterator);
        iterateOneList(mNicknameList, iterator);
        iterateOneList(mNoteList, iterator);
        iterateOneList(mAndroidCustomDataList, iterator);

        if (mBirthday != null) {
            iterator.onElementGroupStarted(mBirthday.getEntryLabel());
            iterator.onElement(mBirthday);
            iterator.onElementGroupEnded();
        }
        if (mAnniversary != null) {
            iterator.onElementGroupStarted(mAnniversary.getEntryLabel());
            iterator.onElement(mAnniversary);
            iterator.onElementGroupEnded();
        }
        iterator.onIterationEnded();
    }

    private void iterateOneList(List<? extends EntryElement> elemList,
            EntryElementIterator iterator) {
        if (elemList != null && elemList.size() > 0) {
            iterator.onElementGroupStarted(elemList.get(0).getEntryLabel());
            for (EntryElement elem : elemList) {
                iterator.onElement(elem);
            }
            iterator.onElementGroupEnded();
        }
    }

    private class IsIgnorableIterator implements EntryElementIterator {
        private boolean mEmpty = true;

        @Override
        public void onIterationStarted() {
        }

        @Override
        public void onIterationEnded() {
        }

        @Override
        public void onElementGroupStarted(EntryLabel label) {
        }

        @Override
        public void onElementGroupEnded() {
        }

        @Override
        public boolean onElement(EntryElement elem) {
            if (!elem.isEmpty()) {
                mEmpty = false;
                // exit now
                return false;
            } else {
                return true;
            }
        }

        public boolean getResult() {
            return mEmpty;
        }
    }

    private class ToStringIterator implements EntryElementIterator {
        private StringBuilder mBuilder;

        private boolean mFirstElement;

        @Override
        public void onIterationStarted() {
            mBuilder = new StringBuilder();
            mBuilder.append("[[hash: " + VCardEntry.this.hashCode() + "\n");
        }

        @Override
        public void onElementGroupStarted(EntryLabel label) {
            mBuilder.append(label.toString() + ": ");
            mFirstElement = true;
        }

        @Override
        public boolean onElement(EntryElement elem) {
            if (!mFirstElement) {
                mBuilder.append(", ");
                mFirstElement = false;
            }
            mBuilder.append("[").append(elem.toString()).append("]");
            return true;
        }

        @Override
        public void onElementGroupEnded() {
            mBuilder.append("\n");
        }

        @Override
        public void onIterationEnded() {
            mBuilder.append("]]\n");
        }

        @Override
        public String toString() {
            return mBuilder.toString();
        }
    }

    private class InsertOperationConstrutor implements EntryElementIterator {
        private final List<ContentProviderOperation> mOperationList;

        private final int mBackReferenceIndex;

        public InsertOperationConstrutor(List<ContentProviderOperation> operationList,
                int backReferenceIndex) {
            mOperationList = operationList;
            mBackReferenceIndex = backReferenceIndex;
        }

        @Override
        public void onIterationStarted() {
        }

        @Override
        public void onIterationEnded() {
        }

        @Override
        public void onElementGroupStarted(EntryLabel label) {
        }

        @Override
        public void onElementGroupEnded() {
        }

        @Override
        public boolean onElement(EntryElement elem) {
            if (!elem.isEmpty()) {
                elem.constructInsertOperation(mOperationList, mBackReferenceIndex);
            }
            return true;
        }
    }

    private final int mVCardType;
    private final Account mAccount;

    private List<VCardEntry> mChildren;

    @Override
    public String toString() {
        ToStringIterator iterator = new ToStringIterator();
        iterateAllData(iterator);
        return iterator.toString();
    }

    public VCardEntry() {
        this(VCardConfig.VCARD_TYPE_V21_GENERIC);
    }

    public VCardEntry(int vcardType) {
        this(vcardType, null);
    }

    public VCardEntry(int vcardType, Account account) {
        mVCardType = vcardType;
        mAccount = account;
    }

    private void addPhone(int type, String data, String label, boolean isPrimary) {
        if (mPhoneList == null) {
            mPhoneList = new ArrayList<PhoneData>();
        }
        final StringBuilder builder = new StringBuilder();
        final String trimmed = data.trim();
        final String formattedNumber;
        if (type == Phone.TYPE_PAGER || VCardConfig.refrainPhoneNumberFormatting(mVCardType)) {
            formattedNumber = trimmed;
        } else {
            // TODO: from the view of vCard spec these auto conversions should be removed.
            // Note that some other codes (like the phone number formatter) or modules expect this
            // auto conversion (bug 5178723), so just omitting this code won't be preferable enough
            // (bug 4177894)
            boolean hasPauseOrWait = false;
            final int length = trimmed.length();
            for (int i = 0; i < length; i++) {
                char ch = trimmed.charAt(i);
                // See RFC 3601 and docs for PhoneNumberUtils for more info.
                if (ch == 'p' || ch == 'P') {
                    builder.append(PhoneNumberUtils.PAUSE);
                    hasPauseOrWait = true;
                } else if (ch == 'w' || ch == 'W') {
                    builder.append(PhoneNumberUtils.WAIT);
                    hasPauseOrWait = true;
                } else if (PhoneNumberUtils.is12Key(ch) || (i == 0 && ch == '+')) {
                    builder.append(ch);
                }
            }
            if (!hasPauseOrWait) {
                final int formattingType = VCardUtils.getPhoneNumberFormat(mVCardType);
                formattedNumber = PhoneNumberUtilsPort.formatNumber(
                        builder.toString(), formattingType);
            } else {
                formattedNumber = builder.toString();
            }
        }
        PhoneData phoneData = new PhoneData(formattedNumber, type, label, isPrimary);
        mPhoneList.add(phoneData);
    }

    private void addSip(String sipData, int type, String label, boolean isPrimary) {
        if (mSipList == null) {
            mSipList = new ArrayList<SipData>();
        }
        mSipList.add(new SipData(sipData, type, label, isPrimary));
    }

    private void addNickName(final String nickName) {
        if (mNicknameList == null) {
            mNicknameList = new ArrayList<NicknameData>();
        }
        mNicknameList.add(new NicknameData(nickName));
    }

    private void addEmail(int type, String data, String label, boolean isPrimary) {
        if (mEmailList == null) {
            mEmailList = new ArrayList<EmailData>();
        }
        mEmailList.add(new EmailData(data, type, label, isPrimary));
    }

    private void addPostal(int type, List<String> propValueList, String label, boolean isPrimary) {
        if (mPostalList == null) {
            mPostalList = new ArrayList<PostalData>(0);
        }
        mPostalList.add(PostalData.constructPostalData(propValueList, type, label, isPrimary,
                mVCardType));
    }

    /**
     * Should be called via {@link #handleOrgValue(int, List, Map, boolean)} or
     * {@link #handleTitleValue(String)}.
     */
    private void addNewOrganization(final String organizationName, final String departmentName,
            final String titleName, final String phoneticName, int type, final boolean isPrimary) {
        if (mOrganizationList == null) {
            mOrganizationList = new ArrayList<OrganizationData>();
        }
        mOrganizationList.add(new OrganizationData(organizationName, departmentName, titleName,
                phoneticName, type, isPrimary));
    }

    private static final List<String> sEmptyList = Collections
            .unmodifiableList(new ArrayList<String>(0));

    private String buildSinglePhoneticNameFromSortAsParam(Map<String, Collection<String>> paramMap) {
        final Collection<String> sortAsCollection = paramMap.get(VCardConstants.PARAM_SORT_AS);
        if (sortAsCollection != null && sortAsCollection.size() != 0) {
            if (sortAsCollection.size() > 1) {
                Log.w(LOG_TAG,
                        "Incorrect multiple SORT_AS parameters detected: "
                                + Arrays.toString(sortAsCollection.toArray()));
            }
            final List<String> sortNames = VCardUtils.constructListFromValue(sortAsCollection
                    .iterator().next(), mVCardType);
            final StringBuilder builder = new StringBuilder();
            for (final String elem : sortNames) {
                builder.append(elem);
            }
            return builder.toString();
        } else {
            return null;
        }
    }

    /**
     * Set "ORG" related values to the appropriate data. If there's more than
     * one {@link OrganizationData} objects, this input data are attached to the
     * last one which does not have valid values (not including empty but only
     * null). If there's no {@link OrganizationData} object, a new
     * {@link OrganizationData} is created, whose title is set to null.
     */
    private void handleOrgValue(final int type, List<String> orgList,
            Map<String, Collection<String>> paramMap, boolean isPrimary) {
        final String phoneticName = buildSinglePhoneticNameFromSortAsParam(paramMap);
        if (orgList == null) {
            orgList = sEmptyList;
        }
        final String organizationName;
        final String departmentName;
        final int size = orgList.size();
        switch (size) {
        case 0: {
            organizationName = "";
            departmentName = null;
            break;
        }
        case 1: {
            organizationName = orgList.get(0);
            departmentName = null;
            break;
        }
        default: { // More than 1.
            organizationName = orgList.get(0);
            // We're not sure which is the correct string for department.
            // In order to keep all the data, concatinate the rest of elements.
            StringBuilder builder = new StringBuilder();
            for (int i = 1; i < size; i++) {
                if (i > 1) {
                    builder.append(' ');
                }
                builder.append(orgList.get(i));
            }
            departmentName = builder.toString();
        }
        }
        if (mOrganizationList == null) {
            // Create new first organization entry, with "null" title which may be
            // added via handleTitleValue().
            addNewOrganization(organizationName, departmentName, null, phoneticName, type,
                    isPrimary);
            return;
        }
        for (OrganizationData organizationData : mOrganizationList) {
            // Not use TextUtils.isEmpty() since ORG was set but the elements might be empty.
            // e.g. "ORG;PREF:;" -> Both companyName and departmentName become empty but not null.
            if (organizationData.mOrganizationName == null
                    && organizationData.mDepartmentName == null) {
                // Probably the "TITLE" property comes before the "ORG" property via
                // handleTitleLine().
                organizationData.mOrganizationName = organizationName;
                organizationData.mDepartmentName = departmentName;
                organizationData.mIsPrimary = isPrimary;
                return;
            }
        }
        // No OrganizatioData is available. Create another one, with "null" title, which may be
        // added via handleTitleValue().
        addNewOrganization(organizationName, departmentName, null, phoneticName, type, isPrimary);
    }

    /**
     * Set "title" value to the appropriate data. If there's more than one
     * OrganizationData objects, this input is attached to the last one which
     * does not have valid title value (not including empty but only null). If
     * there's no OrganizationData object, a new OrganizationData is created,
     * whose company name is set to null.
     */
    private void handleTitleValue(final String title) {
        if (mOrganizationList == null) {
            // Create new first organization entry, with "null" other info, which may be
            // added via handleOrgValue().
            addNewOrganization(null, null, title, null, DEFAULT_ORGANIZATION_TYPE, false);
            return;
        }
        for (OrganizationData organizationData : mOrganizationList) {
            if (organizationData.mTitle == null) {
                organizationData.mTitle = title;
                return;
            }
        }
        // No Organization is available. Create another one, with "null" other info, which may be
        // added via handleOrgValue().
        addNewOrganization(null, null, title, null, DEFAULT_ORGANIZATION_TYPE, false);
    }

    private void addIm(int protocol, String customProtocol, String propValue, int type,
            boolean isPrimary) {
        if (mImList == null) {
            mImList = new ArrayList<ImData>();
        }
        mImList.add(new ImData(protocol, customProtocol, propValue, type, isPrimary));
    }

    private void addNote(final String note) {
        if (mNoteList == null) {
            mNoteList = new ArrayList<NoteData>(1);
        }
        mNoteList.add(new NoteData(note));
    }

    private void addPhotoBytes(String formatName, byte[] photoBytes, boolean isPrimary) {
        if (mPhotoList == null) {
            mPhotoList = new ArrayList<PhotoData>(1);
        }
        final PhotoData photoData = new PhotoData(formatName, photoBytes, isPrimary);
        mPhotoList.add(photoData);
    }

    /**
     * Tries to extract paramMap, constructs SORT-AS parameter values, and store
     * them in appropriate phonetic name variables. This method does not care
     * the vCard version. Even when we have SORT-AS parameters in invalid
     * versions (i.e. 2.1 and 3.0), we scilently accept them so that we won't
     * drop meaningful information. If we had this parameter in the N field of
     * vCard 3.0, and the contact data also have SORT-STRING, we will prefer
     * SORT-STRING, since it is regitimate property to be understood.
     */
    private void tryHandleSortAsName(final Map<String, Collection<String>> paramMap) {
        if (VCardConfig.isVersion30(mVCardType)
                && !(TextUtils.isEmpty(mNameData.mPhoneticFamily)
                        && TextUtils.isEmpty(mNameData.mPhoneticMiddle) && TextUtils
                        .isEmpty(mNameData.mPhoneticGiven))) {
            return;
        }

        final Collection<String> sortAsCollection = paramMap.get(VCardConstants.PARAM_SORT_AS);
        if (sortAsCollection != null && sortAsCollection.size() != 0) {
            if (sortAsCollection.size() > 1) {
                Log.w(LOG_TAG,
                        "Incorrect multiple SORT_AS parameters detected: "
                                + Arrays.toString(sortAsCollection.toArray()));
            }
            final List<String> sortNames = VCardUtils.constructListFromValue(sortAsCollection
                    .iterator().next(), mVCardType);
            int size = sortNames.size();
            if (size > 3) {
                size = 3;
            }
            switch (size) {
            case 3:
                mNameData.mPhoneticMiddle = sortNames.get(2); //$FALL-THROUGH$
            case 2:
                mNameData.mPhoneticGiven = sortNames.get(1); //$FALL-THROUGH$
            default:
                mNameData.mPhoneticFamily = sortNames.get(0);
                break;
            }
        }
    }

    @SuppressWarnings("fallthrough")
    private void handleNProperty(final List<String> paramValues,
            Map<String, Collection<String>> paramMap) {
        // in vCard 4.0, SORT-AS parameter is available.
        tryHandleSortAsName(paramMap);

        // Family, Given, Middle, Prefix, Suffix. (1 - 5)
        int size;
        if (paramValues == null || (size = paramValues.size()) < 1) {
            return;
        }
        if (size > 5) {
            size = 5;
        }

        switch (size) {
        // Fall-through.
        case 5:
            mNameData.mSuffix = paramValues.get(4);
        case 4:
            mNameData.mPrefix = paramValues.get(3);
        case 3:
            mNameData.mMiddle = paramValues.get(2);
        case 2:
            mNameData.mGiven = paramValues.get(1);
        default:
            mNameData.mFamily = paramValues.get(0);
        }
    }

    /**
     * Note: Some Japanese mobile phones use this field for phonetic name, since
     * vCard 2.1 does not have "SORT-STRING" type. Also, in some cases, the
     * field has some ';'s in it. Assume the ';' means the same meaning in N
     * property
     */
    @SuppressWarnings("fallthrough")
    private void handlePhoneticNameFromSound(List<String> elems) {
        if (!(TextUtils.isEmpty(mNameData.mPhoneticFamily)
                && TextUtils.isEmpty(mNameData.mPhoneticMiddle) && TextUtils
                .isEmpty(mNameData.mPhoneticGiven))) {
            // This means the other properties like "X-PHONETIC-FIRST-NAME" was already found.
            // Ignore "SOUND;X-IRMC-N".
            return;
        }

        int size;
        if (elems == null || (size = elems.size()) < 1) {
            return;
        }

        // Assume that the order is "Family, Given, Middle".
        // This is not from specification but mere assumption. Some Japanese
        // phones use this order.
        if (size > 3) {
            size = 3;
        }

        if (elems.get(0).length() > 0) {
            boolean onlyFirstElemIsNonEmpty = true;
            for (int i = 1; i < size; i++) {
                if (elems.get(i).length() > 0) {
                    onlyFirstElemIsNonEmpty = false;
                    break;
                }
            }
            if (onlyFirstElemIsNonEmpty) {
                final String[] namesArray = elems.get(0).split(" ");
                final int nameArrayLength = namesArray.length;
                if (nameArrayLength == 3) {
                    // Assume the string is "Family Middle Given".
                    mNameData.mPhoneticFamily = namesArray[0];
                    mNameData.mPhoneticMiddle = namesArray[1];
                    mNameData.mPhoneticGiven = namesArray[2];
                } else if (nameArrayLength == 2) {
                    // Assume the string is "Family Given" based on the Japanese mobile
                    // phones' preference.
                    mNameData.mPhoneticFamily = namesArray[0];
                    mNameData.mPhoneticGiven = namesArray[1];
                } else {
                    mNameData.mPhoneticGiven = elems.get(0);
                }
                return;
            }
        }

        switch (size) {
        // fallthrough
        case 3:
            mNameData.mPhoneticMiddle = elems.get(2);
        case 2:
            mNameData.mPhoneticGiven = elems.get(1);
        default:
            mNameData.mPhoneticFamily = elems.get(0);
        }
    }

    public void addProperty(final VCardProperty property) {
        final String propertyName = property.getName();
        final Map<String, Collection<String>> paramMap = property.getParameterMap();
        final List<String> propertyValueList = property.getValueList();
        byte[] propertyBytes = property.getByteValue();

        if ((propertyValueList == null || propertyValueList.size() == 0)
                && propertyBytes == null) {
            return;
        }
        final String propValue = (propertyValueList != null
                ? listToString(propertyValueList).trim()
                : null);

        if (propertyName.equals(VCardConstants.PROPERTY_VERSION)) {
            // vCard version. Ignore this.
        } else if (propertyName.equals(VCardConstants.PROPERTY_FN)) {
            mNameData.mFormatted = propValue;
        } else if (propertyName.equals(VCardConstants.PROPERTY_NAME)) {
            // Only in vCard 3.0. Use this if FN doesn't exist though it is
            // required in vCard 3.0.
            if (TextUtils.isEmpty(mNameData.mFormatted)) {
                mNameData.mFormatted = propValue;
            }
        } else if (propertyName.equals(VCardConstants.PROPERTY_N)) {
            handleNProperty(propertyValueList, paramMap);
        } else if (propertyName.equals(VCardConstants.PROPERTY_SORT_STRING)) {
            mNameData.mSortString = propValue;
        } else if (propertyName.equals(VCardConstants.PROPERTY_NICKNAME)
                || propertyName.equals(VCardConstants.ImportOnly.PROPERTY_X_NICKNAME)) {
            addNickName(propValue);
        } else if (propertyName.equals(VCardConstants.PROPERTY_SOUND)) {
            Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
            if (typeCollection != null
                    && typeCollection.contains(VCardConstants.PARAM_TYPE_X_IRMC_N)) {
                // As of 2009-10-08, Parser side does not split a property value into separated
                // values using ';' (in other words, propValueList.size() == 1),
                // which is correct behavior from the view of vCard 2.1.
                // But we want it to be separated, so do the separation here.
                final List<String> phoneticNameList = VCardUtils.constructListFromValue(propValue,
                        mVCardType);
                handlePhoneticNameFromSound(phoneticNameList);
            } else {
                // Ignore this field since Android cannot understand what it is.
            }
        } else if (propertyName.equals(VCardConstants.PROPERTY_ADR)) {
            boolean valuesAreAllEmpty = true;
            for (String value : propertyValueList) {
                if (!TextUtils.isEmpty(value)) {
                    valuesAreAllEmpty = false;
                    break;
                }
            }
            if (valuesAreAllEmpty) {
                return;
            }

            int type = -1;
            String label = null;
            boolean isPrimary = false;
            final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
            if (typeCollection != null) {
                for (final String typeStringOrg : typeCollection) {
                    final String typeStringUpperCase = typeStringOrg.toUpperCase();
                    if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_PREF)) {
                        isPrimary = true;
                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_HOME)) {
                        type = StructuredPostal.TYPE_HOME;
                        label = null;
                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_WORK)
                            || typeStringUpperCase
                                    .equalsIgnoreCase(VCardConstants.PARAM_EXTRA_TYPE_COMPANY)) {
                        // "COMPANY" seems emitted by Windows Mobile, which is not
                        // specifically supported by vCard 2.1. We assume this is same
                        // as "WORK".
                        type = StructuredPostal.TYPE_WORK;
                        label = null;
                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_ADR_TYPE_PARCEL)
                            || typeStringUpperCase.equals(VCardConstants.PARAM_ADR_TYPE_DOM)
                            || typeStringUpperCase.equals(VCardConstants.PARAM_ADR_TYPE_INTL)) {
                        // We do not have any appropriate way to store this information.
                    } else if (type < 0) { // If no other type is specified before.
                        type = StructuredPostal.TYPE_CUSTOM;
                        if (typeStringUpperCase.startsWith("X-")) { // If X- or x-
                            label = typeStringOrg.substring(2);
                        } else {
                            label = typeStringOrg;
                        }
                    }
                }
            }
            // We use "HOME" as default
            if (type < 0) {
                type = StructuredPostal.TYPE_HOME;
            }

            addPostal(type, propertyValueList, label, isPrimary);
        } else if (propertyName.equals(VCardConstants.PROPERTY_EMAIL)) {
            int type = -1;
            String label = null;
            boolean isPrimary = false;
            final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
            if (typeCollection != null) {
                for (final String typeStringOrg : typeCollection) {
                    final String typeStringUpperCase = typeStringOrg.toUpperCase();
                    if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_PREF)) {
                        isPrimary = true;
                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_HOME)) {
                        type = Email.TYPE_HOME;
                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_WORK)) {
                        type = Email.TYPE_WORK;
                    } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_CELL)) {
                        type = Email.TYPE_MOBILE;
                    } else if (type < 0) { // If no other type is specified before
                        if (typeStringUpperCase.startsWith("X-")) { // If X- or x-
                            label = typeStringOrg.substring(2);
                        } else {
                            label = typeStringOrg;
                        }
                        type = Email.TYPE_CUSTOM;
                    }
                }
            }
            if (type < 0) {
                type = Email.TYPE_OTHER;
            }
            addEmail(type, propValue, label, isPrimary);
        } else if (propertyName.equals(VCardConstants.PROPERTY_ORG)) {
            // vCard specification does not specify other types.
            final int type = Organization.TYPE_WORK;
            boolean isPrimary = false;
            Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
            if (typeCollection != null) {
                for (String typeString : typeCollection) {
                    if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) {
                        isPrimary = true;
                    }
                }
            }
            handleOrgValue(type, propertyValueList, paramMap, isPrimary);
        } else if (propertyName.equals(VCardConstants.PROPERTY_TITLE)) {
            handleTitleValue(propValue);
        } else if (propertyName.equals(VCardConstants.PROPERTY_ROLE)) {
            // This conflicts with TITLE. Ignore for now...
            // handleTitleValue(propValue);
        } else if (propertyName.equals(VCardConstants.PROPERTY_PHOTO)
                || propertyName.equals(VCardConstants.PROPERTY_LOGO)) {
            Collection<String> paramMapValue = paramMap.get("VALUE");
            if (paramMapValue != null && paramMapValue.contains("URL")) {
                // Currently we do not have appropriate example for testing this case.
            } else {
                final Collection<String> typeCollection = paramMap.get("TYPE");
                String formatName = null;
                boolean isPrimary = false;
                if (typeCollection != null) {
                    for (String typeValue : typeCollection) {
                        if (VCardConstants.PARAM_TYPE_PREF.equals(typeValue)) {
                            isPrimary = true;
                        } else if (formatName == null) {
                            formatName = typeValue;
                        }
                    }
                }
                addPhotoBytes(formatName, propertyBytes, isPrimary);
            }
        } else if (propertyName.equals(VCardConstants.PROPERTY_TEL)) {
            String phoneNumber = null;
            boolean isSip = false;
            if (VCardConfig.isVersion40(mVCardType)) {
                // Given propValue is in URI format, not in phone number format used until
                // vCard 3.0.
                if (propValue.startsWith("sip:")) {
                    isSip = true;
                } else if (propValue.startsWith("tel:")) {
                    phoneNumber = propValue.substring(4);
                } else {
                    // We don't know appropriate way to handle the other schemas. Also,
                    // we may still have non-URI phone number. To keep given data as much as
                    // we can, just save original value here.
                    phoneNumber = propValue;
                }
            } else {
                phoneNumber = propValue;
            }

            if (isSip) {
                final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
                handleSipCase(propValue, typeCollection);
            } else {
                if (propValue.length() == 0) {
                    return;
                }

                final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
                final Object typeObject = VCardUtils.getPhoneTypeFromStrings(typeCollection,
                        phoneNumber);
                final int type;
                final String label;
                if (typeObject instanceof Integer) {
                    type = (Integer) typeObject;
                    label = null;
                } else {
                    type = Phone.TYPE_CUSTOM;
                    label = typeObject.toString();
                }

                final boolean isPrimary;
                if (typeCollection != null &&
                        typeCollection.contains(VCardConstants.PARAM_TYPE_PREF)) {
                    isPrimary = true;
                } else {
                    isPrimary = false;
                }

                addPhone(type, phoneNumber, label, isPrimary);
            }
        } else if (propertyName.equals(VCardConstants.PROPERTY_X_SKYPE_PSTNNUMBER)) {
            // The phone number available via Skype.
            Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
            final int type = Phone.TYPE_OTHER;
            final boolean isPrimary;
            if (typeCollection != null
                    && typeCollection.contains(VCardConstants.PARAM_TYPE_PREF)) {
                isPrimary = true;
            } else {
                isPrimary = false;
            }
            addPhone(type, propValue, null, isPrimary);
        } else if (sImMap.containsKey(propertyName)) {
            final int protocol = sImMap.get(propertyName);
            boolean isPrimary = false;
            int type = -1;
            final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
            if (typeCollection != null) {
                for (String typeString : typeCollection) {
                    if (typeString.equals(VCardConstants.PARAM_TYPE_PREF)) {
                        isPrimary = true;
                    } else if (type < 0) {
                        if (typeString.equalsIgnoreCase(VCardConstants.PARAM_TYPE_HOME)) {
                            type = Im.TYPE_HOME;
                        } else if (typeString.equalsIgnoreCase(VCardConstants.PARAM_TYPE_WORK)) {
                            type = Im.TYPE_WORK;
                        }
                    }
                }
            }
            if (type < 0) {
                type = Im.TYPE_HOME;
            }
            addIm(protocol, null, propValue, type, isPrimary);
        } else if (propertyName.equals(VCardConstants.PROPERTY_NOTE)) {
            addNote(propValue);
        } else if (propertyName.equals(VCardConstants.PROPERTY_URL)) {
            if (mWebsiteList == null) {
                mWebsiteList = new ArrayList<WebsiteData>(1);
            }
            mWebsiteList.add(new WebsiteData(propValue));
        } else if (propertyName.equals(VCardConstants.PROPERTY_BDAY)) {
            mBirthday = new BirthdayData(propValue);
        } else if (propertyName.equals(VCardConstants.PROPERTY_ANNIVERSARY)) {
            mAnniversary = new AnniversaryData(propValue);
        } else if (propertyName.equals(VCardConstants.PROPERTY_X_PHONETIC_FIRST_NAME)) {
            mNameData.mPhoneticGiven = propValue;
        } else if (propertyName.equals(VCardConstants.PROPERTY_X_PHONETIC_MIDDLE_NAME)) {
            mNameData.mPhoneticMiddle = propValue;
        } else if (propertyName.equals(VCardConstants.PROPERTY_X_PHONETIC_LAST_NAME)) {
            mNameData.mPhoneticFamily = propValue;
        } else if (propertyName.equals(VCardConstants.PROPERTY_IMPP)) {
            // See also RFC 4770 (for vCard 3.0)
            if (propValue.startsWith("sip:")) {
                final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
                handleSipCase(propValue, typeCollection);
            }
        } else if (propertyName.equals(VCardConstants.PROPERTY_X_SIP)) {
            if (!TextUtils.isEmpty(propValue)) {
                final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
                handleSipCase(propValue, typeCollection);
            }
        } else if (propertyName.equals(VCardConstants.PROPERTY_X_ANDROID_CUSTOM)) {
            final List<String> customPropertyList = VCardUtils.constructListFromValue(propValue,
                    mVCardType);
            handleAndroidCustomProperty(customPropertyList);
        } else if (propertyName.toUpperCase().startsWith("X-")) {
            // Catch all for X- properties. The caller can decide what to do with these.
            if (mUnknownXData == null) {
                mUnknownXData = new ArrayList<Pair<String, String>>();
            }
            mUnknownXData.add(new Pair<String, String>(propertyName, propValue));
        } else {
        }
        // Be careful when adding some logic here, as some blocks above may use "return".
    }

    /**
     * @param propValue may contain "sip:" at the beginning.
     * @param typeCollection
     */
    private void handleSipCase(String propValue, Collection<String> typeCollection) {
        if (TextUtils.isEmpty(propValue)) {
            return;
        }
        if (propValue.startsWith("sip:")) {
            propValue = propValue.substring(4);
            if (propValue.length() == 0) {
                return;
            }
        }

        int type = -1;
        String label = null;
        boolean isPrimary = false;
        if (typeCollection != null) {
            for (final String typeStringOrg : typeCollection) {
                final String typeStringUpperCase = typeStringOrg.toUpperCase();
                if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_PREF)) {
                    isPrimary = true;
                } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_HOME)) {
                    type = SipAddress.TYPE_HOME;
                } else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_WORK)) {
                    type = SipAddress.TYPE_WORK;
                } else if (type < 0) { // If no other type is specified before
                    if (typeStringUpperCase.startsWith("X-")) { // If X- or x-
                        label = typeStringOrg.substring(2);
                    } else {
                        label = typeStringOrg;
                    }
                    type = SipAddress.TYPE_CUSTOM;
                }
            }
        }
        if (type < 0) {
            type = SipAddress.TYPE_OTHER;
        }
        addSip(propValue, type, label, isPrimary);
    }

    public void addChild(VCardEntry child) {
        if (mChildren == null) {
            mChildren = new ArrayList<VCardEntry>();
        }
        mChildren.add(child);
    }

    private void handleAndroidCustomProperty(final List<String> customPropertyList) {
        if (mAndroidCustomDataList == null) {
            mAndroidCustomDataList = new ArrayList<AndroidCustomData>();
        }
        mAndroidCustomDataList
                .add(AndroidCustomData.constructAndroidCustomData(customPropertyList));
    }

    /**
     * Construct the display name. The constructed data must not be null.
     */
    private String constructDisplayName() {
        String displayName = null;
        // FullName (created via "FN" or "NAME" field) is prefered.
        if (!TextUtils.isEmpty(mNameData.mFormatted)) {
            displayName = mNameData.mFormatted;
        } else if (!mNameData.emptyStructuredName()) {
            displayName = VCardUtils.constructNameFromElements(mVCardType, mNameData.mFamily,
                    mNameData.mMiddle, mNameData.mGiven, mNameData.mPrefix, mNameData.mSuffix);
        } else if (!mNameData.emptyPhoneticStructuredName()) {
            displayName = VCardUtils.constructNameFromElements(mVCardType,
                    mNameData.mPhoneticFamily, mNameData.mPhoneticMiddle, mNameData.mPhoneticGiven);
        } else if (mEmailList != null && mEmailList.size() > 0) {
            displayName = mEmailList.get(0).mAddress;
        } else if (mPhoneList != null && mPhoneList.size() > 0) {
            displayName = mPhoneList.get(0).mNumber;
        } else if (mPostalList != null && mPostalList.size() > 0) {
            displayName = mPostalList.get(0).getFormattedAddress(mVCardType);
        } else if (mOrganizationList != null && mOrganizationList.size() > 0) {
            displayName = mOrganizationList.get(0).getFormattedString();
        }
        if (displayName == null) {
            displayName = "";
        }
        return displayName;
    }

    /**
     * Consolidate several fielsds (like mName) using name candidates,
     */
    public void consolidateFields() {
        mNameData.displayName = constructDisplayName();
    }

    /**
     * @return true when this object has nothing meaningful for Android's
     *         Contacts, and thus is "ignorable" for Android's Contacts. This
     *         does not mean an original vCard is really empty. Even when the
     *         original vCard has some fields, this may ignore it if those
     *         fields cannot be transcoded into Android's Contacts
     *         representation.
     */
    public boolean isIgnorable() {
        IsIgnorableIterator iterator = new IsIgnorableIterator();
        iterateAllData(iterator);
        return iterator.getResult();
    }

    /**
     * Constructs the list of insert operation for this object. When the
     * operationList argument is null, this method creates a new ArrayList and
     * return it. The returned object is filled with new insert operations for
     * this object. When operationList argument is not null, this method appends
     * those new operations into the object instead of creating a new ArrayList.
     *
     * @param resolver {@link ContentResolver} object to be used in this method.
     * @param operationList object to be filled. You can use this argument to
     *            concatinate operation lists. If null, this method creates a
     *            new array object.
     * @return If operationList argument is null, new object with new insert
     *         operations. If it is not null, the operationList object with
     *         operations inserted by this method.
     */
    public ArrayList<ContentProviderOperation> constructInsertOperations(ContentResolver resolver,
            ArrayList<ContentProviderOperation> operationList) {
        if (operationList == null) {
            operationList = new ArrayList<ContentProviderOperation>();
        }

        if (isIgnorable()) {
            return operationList;
        }

        final int backReferenceIndex = operationList.size();

        // After applying the batch the first result's Uri is returned so it is important that
        // the RawContact is the first operation that gets inserted into the list.
        ContentProviderOperation.Builder builder = ContentProviderOperation
                .newInsert(RawContacts.CONTENT_URI);
        if (mAccount != null) {
            builder.withValue(RawContacts.ACCOUNT_NAME, mAccount.name);
            builder.withValue(RawContacts.ACCOUNT_TYPE, mAccount.type);
        } else {
            builder.withValue(RawContacts.ACCOUNT_NAME, null);
            builder.withValue(RawContacts.ACCOUNT_TYPE, null);
        }
        // contacts favorites
        if (getStarred()) {
            builder.withValue(RawContacts.STARRED, 1);
        }
        operationList.add(builder.build());

        int start = operationList.size();
        iterateAllData(new InsertOperationConstrutor(operationList, backReferenceIndex));
        int end = operationList.size();

        return operationList;
    }

    public static VCardEntry buildFromResolver(ContentResolver resolver) {
        return buildFromResolver(resolver, Contacts.CONTENT_URI);
    }

    public static VCardEntry buildFromResolver(ContentResolver resolver, Uri uri) {
        return null;
    }

    private String listToString(List<String> list) {
        final int size = list.size();
        if (size > 1) {
            StringBuilder builder = new StringBuilder();
            int i = 0;
            for (String type : list) {
                builder.append(type);
                if (i < size - 1) {
                    builder.append(";");
                }
            }
            return builder.toString();
        } else if (size == 1) {
            return list.get(0);
        } else {
            return "";
        }
    }

    public final NameData getNameData() {
        return mNameData;
    }

    public final List<NicknameData> getNickNameList() {
        return mNicknameList;
    }

    public final String getBirthday() {
        return mBirthday != null ? mBirthday.mBirthday : null;
    }

    public final List<NoteData> getNotes() {
        return mNoteList;
    }

    public final List<PhoneData> getPhoneList() {
        return mPhoneList;
    }

    public final List<EmailData> getEmailList() {
        return mEmailList;
    }

    public final List<PostalData> getPostalList() {
        return mPostalList;
    }

    public final List<OrganizationData> getOrganizationList() {
        return mOrganizationList;
    }

    public final List<ImData> getImList() {
        return mImList;
    }

    public final List<PhotoData> getPhotoList() {
        return mPhotoList;
    }

    public final List<WebsiteData> getWebsiteList() {
        return mWebsiteList;
    }

    /**
     * @hide this interface may be changed for better support of vCard 4.0 (UID)
     */
    public final List<VCardEntry> getChildlen() {
        return mChildren;
    }

    public String getDisplayName() {
        if (mNameData.displayName == null) {
            mNameData.displayName = constructDisplayName();
        }
        return mNameData.displayName;
    }

    public List<Pair<String, String>> getUnknownXData() {
        return mUnknownXData;
    }
}
