/*
 * Copyright (C) 2008-2009 Marc Blank
 * Licensed to 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.exchange.adapter;

import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentProviderOperation.Builder;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Entity;
import android.content.Entity.NamedContentValues;
import android.content.EntityIterator;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
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.Relation;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.RawContactsEntity;
import android.provider.ContactsContract.Settings;
import android.provider.ContactsContract.SyncState;
import android.provider.SyncStateContract;
import android.text.TextUtils;
import android.text.util.Rfc822Token;
import android.text.util.Rfc822Tokenizer;
import android.util.Base64;
import android.util.Log;

import com.android.exchange.CommandStatusException;
import com.android.exchange.Eas;
import com.android.exchange.EasSyncService;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

/**
 * Sync adapter for EAS Contacts
 *
 */
public class ContactsSyncAdapter extends AbstractSyncAdapter {

    private static final String TAG = "EasContactsSyncAdapter";
    private static final String SERVER_ID_SELECTION = RawContacts.SOURCE_ID + "=?";
    private static final String CLIENT_ID_SELECTION = RawContacts.SYNC1 + "=?";
    private static final String[] ID_PROJECTION = new String[] {RawContacts._ID};
    private static final String[] GROUP_TITLE_PROJECTION = new String[] {Groups.TITLE};
    private static final String MIMETYPE_GROUP_MEMBERSHIP_AND_ID_EQUALS = Data.MIMETYPE + "='" +
        GroupMembership.CONTENT_ITEM_TYPE + "' AND " + GroupMembership.GROUP_ROW_ID + "=?";
    private static final String[] GROUPS_ID_PROJECTION = new String[] {Groups._ID};

    private static final ArrayList<NamedContentValues> EMPTY_ARRAY_NAMEDCONTENTVALUES
        = new ArrayList<NamedContentValues>();

    private static final String FOUND_DATA_ROW = "com.android.exchange.FOUND_ROW";

    private static final int[] HOME_ADDRESS_TAGS = new int[] {Tags.CONTACTS_HOME_ADDRESS_CITY,
        Tags.CONTACTS_HOME_ADDRESS_COUNTRY,
        Tags.CONTACTS_HOME_ADDRESS_POSTAL_CODE,
        Tags.CONTACTS_HOME_ADDRESS_STATE,
        Tags.CONTACTS_HOME_ADDRESS_STREET};

    private static final int[] WORK_ADDRESS_TAGS = new int[] {Tags.CONTACTS_BUSINESS_ADDRESS_CITY,
        Tags.CONTACTS_BUSINESS_ADDRESS_COUNTRY,
        Tags.CONTACTS_BUSINESS_ADDRESS_POSTAL_CODE,
        Tags.CONTACTS_BUSINESS_ADDRESS_STATE,
        Tags.CONTACTS_BUSINESS_ADDRESS_STREET};

    private static final int[] OTHER_ADDRESS_TAGS = new int[] {Tags.CONTACTS_HOME_ADDRESS_CITY,
        Tags.CONTACTS_OTHER_ADDRESS_COUNTRY,
        Tags.CONTACTS_OTHER_ADDRESS_POSTAL_CODE,
        Tags.CONTACTS_OTHER_ADDRESS_STATE,
        Tags.CONTACTS_OTHER_ADDRESS_STREET};

    private static final int MAX_IM_ROWS = 3;
    private static final int MAX_EMAIL_ROWS = 3;
    private static final int MAX_PHONE_ROWS = 2;
    private static final String COMMON_DATA_ROW = Im.DATA;  // Could have been Email.DATA, etc.
    private static final String COMMON_TYPE_ROW = Phone.TYPE; // Could have been any typed row

    private static final int[] IM_TAGS = new int[] {Tags.CONTACTS2_IM_ADDRESS,
        Tags.CONTACTS2_IM_ADDRESS_2, Tags.CONTACTS2_IM_ADDRESS_3};

    private static final int[] EMAIL_TAGS = new int[] {Tags.CONTACTS_EMAIL1_ADDRESS,
        Tags.CONTACTS_EMAIL2_ADDRESS, Tags.CONTACTS_EMAIL3_ADDRESS};

    private static final int[] WORK_PHONE_TAGS = new int[] {Tags.CONTACTS_BUSINESS_TELEPHONE_NUMBER,
        Tags.CONTACTS_BUSINESS2_TELEPHONE_NUMBER};

    private static final int[] HOME_PHONE_TAGS = new int[] {Tags.CONTACTS_HOME_TELEPHONE_NUMBER,
        Tags.CONTACTS_HOME2_TELEPHONE_NUMBER};

    private static final Object sSyncKeyLock = new Object();

    ArrayList<Long> mDeletedIdList = new ArrayList<Long>();
    ArrayList<Long> mUpdatedIdList = new ArrayList<Long>();

    private final Uri mAccountUri;
    private final ContentResolver mContentResolver;
    private boolean mGroupsUsed = false;

    public ContactsSyncAdapter(EasSyncService service) {
        super(service);
        mAccountUri = uriWithAccountAndIsSyncAdapter(RawContacts.CONTENT_URI);
        mContentResolver = mContext.getContentResolver();
    }

    static Uri addCallerIsSyncAdapterParameter(Uri uri) {
        return uri.buildUpon()
                .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
                .build();
    }

    @Override
    public void sendSyncOptions(Double protocolVersion, Serializer s) throws IOException  {
        setPimSyncOptions(protocolVersion, null, s);
    }

    @Override
    public boolean isSyncable() {
        return ContentResolver.getSyncAutomatically(
                mAccountManagerAccount, ContactsContract.AUTHORITY);
    }

    @Override
    public boolean parse(InputStream is) throws IOException, CommandStatusException {
        EasContactsSyncParser p = new EasContactsSyncParser(is, this);
        return p.parse();
    }


    @Override
    public void wipe() {
        mContentResolver.delete(mAccountUri, null, null);
    }

    interface UntypedRow {
        public void addValues(RowBuilder builder);
        public boolean isSameAs(int type, String value);
    }

    /**
     * We get our SyncKey from ContactsProvider.  If there's not one, we set it to "0" (the reset
     * state) and save that away.
     */
    @Override
    public String getSyncKey() throws IOException {
        synchronized (sSyncKeyLock) {
            ContentProviderClient client = mService.mContentResolver
                    .acquireContentProviderClient(ContactsContract.AUTHORITY_URI);
            try {
                byte[] data = SyncStateContract.Helpers.get(client,
                        ContactsContract.SyncState.CONTENT_URI, mAccountManagerAccount);
                if (data == null || data.length == 0) {
                    // Initialize the SyncKey
                    setSyncKey("0", false);
                    // Make sure ungrouped contacts for Exchange are defaultly visible
                    ContentValues cv = new ContentValues();
                    cv.put(Groups.ACCOUNT_NAME, mAccount.mEmailAddress);
                    cv.put(Groups.ACCOUNT_TYPE, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
                    cv.put(Settings.UNGROUPED_VISIBLE, true);
                    client.insert(addCallerIsSyncAdapterParameter(Settings.CONTENT_URI), cv);
                    return "0";
                } else {
                    return new String(data);
                }
            } catch (RemoteException e) {
                throw new IOException("Can't get SyncKey from ContactsProvider");
            }
        }
    }

    /**
     * We only need to set this when we're forced to make the SyncKey "0" (a reset).  In all other
     * cases, the SyncKey is set within ContactOperations
     */
    @Override
    public void setSyncKey(String syncKey, boolean inCommands) throws IOException {
        synchronized (sSyncKeyLock) {
            if ("0".equals(syncKey) || !inCommands) {
                ContentProviderClient client = mService.mContentResolver
                        .acquireContentProviderClient(ContactsContract.AUTHORITY_URI);
                try {
                    SyncStateContract.Helpers.set(client, ContactsContract.SyncState.CONTENT_URI,
                            mAccountManagerAccount, syncKey.getBytes());
                    userLog("SyncKey set to ", syncKey, " in ContactsProvider");
                } catch (RemoteException e) {
                    throw new IOException("Can't set SyncKey in ContactsProvider");
                }
            }
            mMailbox.mSyncKey = syncKey;
        }
    }

    public static final class EasChildren {
        private EasChildren() {}

        /** MIME type used when storing this in data table. */
        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/eas_children";
        public static final int MAX_CHILDREN = 8;
        public static final String[] ROWS =
            new String[] {"data2", "data3", "data4", "data5", "data6", "data7", "data8", "data9"};
    }

    public static final class EasPersonal {
        String anniversary;
        String fileAs;

            /** MIME type used when storing this in data table. */
        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/eas_personal";
        public static final String ANNIVERSARY = "data2";
        public static final String FILE_AS = "data4";

        boolean hasData() {
            return anniversary != null || fileAs != null;
        }
    }

    public static final class EasBusiness {
        String customerId;
        String governmentId;
        String accountName;

        /** MIME type used when storing this in data table. */
        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/eas_business";
        public static final String CUSTOMER_ID = "data6";
        public static final String GOVERNMENT_ID = "data7";
        public static final String ACCOUNT_NAME = "data8";

        boolean hasData() {
            return customerId != null || governmentId != null || accountName != null;
        }
    }

    public static final class Address {
        String city;
        String country;
        String code;
        String street;
        String state;

        boolean hasData() {
            return city != null || country != null || code != null || state != null
                || street != null;
        }
    }

    class EmailRow implements UntypedRow {
        String email;
        String displayName;

        public EmailRow(String _email) {
            Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(_email);
            // Can't happen, but belt & suspenders
            if (tokens.length == 0) {
                email = "";
                displayName = "";
            } else {
                Rfc822Token token = tokens[0];
                email = token.getAddress();
                displayName = token.getName();
            }
        }

        public void addValues(RowBuilder builder) {
            builder.withValue(Email.DATA, email);
            builder.withValue(Email.DISPLAY_NAME, displayName);
        }

        public boolean isSameAs(int type, String value) {
            return email.equalsIgnoreCase(value);
        }
    }

    class ImRow implements UntypedRow {
        String im;

        public ImRow(String _im) {
            im = _im;
        }

        public void addValues(RowBuilder builder) {
            builder.withValue(Im.DATA, im);
        }

        public boolean isSameAs(int type, String value) {
            return im.equalsIgnoreCase(value);
        }
    }

    class PhoneRow implements UntypedRow {
        String phone;
        int type;

        public PhoneRow(String _phone, int _type) {
            phone = _phone;
            type = _type;
        }

        public void addValues(RowBuilder builder) {
            builder.withValue(Im.DATA, phone);
            builder.withValue(Phone.TYPE, type);
        }

        public boolean isSameAs(int _type, String value) {
            return type == _type && phone.equalsIgnoreCase(value);
        }
    }

   class EasContactsSyncParser extends AbstractSyncParser {

        String[] mBindArgument = new String[1];
        String mMailboxIdAsString;
        ContactOperations ops = new ContactOperations();

        public EasContactsSyncParser(InputStream in, ContactsSyncAdapter adapter)
                throws IOException {
            super(in, adapter);
        }

        public void addData(String serverId, ContactOperations ops, Entity entity)
                throws IOException {
            String fileAs = null;
            String prefix = null;
            String firstName = null;
            String lastName = null;
            String middleName = null;
            String suffix = null;
            String companyName = null;
            String yomiFirstName = null;
            String yomiLastName = null;
            String yomiCompanyName = null;
            String title = null;
            String department = null;
            String officeLocation = null;
            Address home = new Address();
            Address work = new Address();
            Address other = new Address();
            EasBusiness business = new EasBusiness();
            EasPersonal personal = new EasPersonal();
            ArrayList<String> children = new ArrayList<String>();
            ArrayList<UntypedRow> emails = new ArrayList<UntypedRow>();
            ArrayList<UntypedRow> ims = new ArrayList<UntypedRow>();
            ArrayList<UntypedRow> homePhones = new ArrayList<UntypedRow>();
            ArrayList<UntypedRow> workPhones = new ArrayList<UntypedRow>();
            if (entity == null) {
                ops.newContact(serverId);
            }

            while (nextTag(Tags.SYNC_APPLICATION_DATA) != END) {
                switch (tag) {
                    case Tags.CONTACTS_FIRST_NAME:
                        firstName = getValue();
                        break;
                    case Tags.CONTACTS_LAST_NAME:
                        lastName = getValue();
                        break;
                    case Tags.CONTACTS_MIDDLE_NAME:
                        middleName = getValue();
                        break;
                    case Tags.CONTACTS_FILE_AS:
                        fileAs = getValue();
                        break;
                    case Tags.CONTACTS_SUFFIX:
                        suffix = getValue();
                        break;
                    case Tags.CONTACTS_COMPANY_NAME:
                        companyName = getValue();
                        break;
                    case Tags.CONTACTS_JOB_TITLE:
                        title = getValue();
                        break;
                    case Tags.CONTACTS_EMAIL1_ADDRESS:
                    case Tags.CONTACTS_EMAIL2_ADDRESS:
                    case Tags.CONTACTS_EMAIL3_ADDRESS:
                        emails.add(new EmailRow(getValue()));
                        break;
                    case Tags.CONTACTS_BUSINESS2_TELEPHONE_NUMBER:
                    case Tags.CONTACTS_BUSINESS_TELEPHONE_NUMBER:
                        workPhones.add(new PhoneRow(getValue(), Phone.TYPE_WORK));
                        break;
                    case Tags.CONTACTS2_MMS:
                        ops.addPhone(entity, Phone.TYPE_MMS, getValue());
                        break;
                    case Tags.CONTACTS_BUSINESS_FAX_NUMBER:
                        ops.addPhone(entity, Phone.TYPE_FAX_WORK, getValue());
                        break;
                    case Tags.CONTACTS2_COMPANY_MAIN_PHONE:
                        ops.addPhone(entity, Phone.TYPE_COMPANY_MAIN, getValue());
                        break;
                    case Tags.CONTACTS_HOME_FAX_NUMBER:
                        ops.addPhone(entity, Phone.TYPE_FAX_HOME, getValue());
                        break;
                    case Tags.CONTACTS_HOME_TELEPHONE_NUMBER:
                    case Tags.CONTACTS_HOME2_TELEPHONE_NUMBER:
                        homePhones.add(new PhoneRow(getValue(), Phone.TYPE_HOME));
                        break;
                    case Tags.CONTACTS_MOBILE_TELEPHONE_NUMBER:
                        ops.addPhone(entity, Phone.TYPE_MOBILE, getValue());
                        break;
                    case Tags.CONTACTS_CAR_TELEPHONE_NUMBER:
                        ops.addPhone(entity, Phone.TYPE_CAR, getValue());
                        break;
                    case Tags.CONTACTS_RADIO_TELEPHONE_NUMBER:
                        ops.addPhone(entity, Phone.TYPE_RADIO, getValue());
                        break;
                    case Tags.CONTACTS_PAGER_NUMBER:
                        ops.addPhone(entity, Phone.TYPE_PAGER, getValue());
                        break;
                    case Tags.CONTACTS_ASSISTANT_TELEPHONE_NUMBER:
                        ops.addPhone(entity, Phone.TYPE_ASSISTANT, getValue());
                        break;
                    case Tags.CONTACTS2_IM_ADDRESS:
                    case Tags.CONTACTS2_IM_ADDRESS_2:
                    case Tags.CONTACTS2_IM_ADDRESS_3:
                        ims.add(new ImRow(getValue()));
                        break;
                    case Tags.CONTACTS_BUSINESS_ADDRESS_CITY:
                        work.city = getValue();
                        break;
                    case Tags.CONTACTS_BUSINESS_ADDRESS_COUNTRY:
                        work.country = getValue();
                        break;
                    case Tags.CONTACTS_BUSINESS_ADDRESS_POSTAL_CODE:
                        work.code = getValue();
                        break;
                    case Tags.CONTACTS_BUSINESS_ADDRESS_STATE:
                        work.state = getValue();
                        break;
                    case Tags.CONTACTS_BUSINESS_ADDRESS_STREET:
                        work.street = getValue();
                        break;
                    case Tags.CONTACTS_HOME_ADDRESS_CITY:
                        home.city = getValue();
                        break;
                    case Tags.CONTACTS_HOME_ADDRESS_COUNTRY:
                        home.country = getValue();
                        break;
                    case Tags.CONTACTS_HOME_ADDRESS_POSTAL_CODE:
                        home.code = getValue();
                        break;
                    case Tags.CONTACTS_HOME_ADDRESS_STATE:
                        home.state = getValue();
                        break;
                    case Tags.CONTACTS_HOME_ADDRESS_STREET:
                        home.street = getValue();
                        break;
                    case Tags.CONTACTS_OTHER_ADDRESS_CITY:
                        other.city = getValue();
                        break;
                    case Tags.CONTACTS_OTHER_ADDRESS_COUNTRY:
                        other.country = getValue();
                        break;
                    case Tags.CONTACTS_OTHER_ADDRESS_POSTAL_CODE:
                        other.code = getValue();
                        break;
                    case Tags.CONTACTS_OTHER_ADDRESS_STATE:
                        other.state = getValue();
                        break;
                    case Tags.CONTACTS_OTHER_ADDRESS_STREET:
                        other.street = getValue();
                        break;

                    case Tags.CONTACTS_CHILDREN:
                        childrenParser(children);
                        break;

                    case Tags.CONTACTS_YOMI_COMPANY_NAME:
                        yomiCompanyName = getValue();
                        break;
                    case Tags.CONTACTS_YOMI_FIRST_NAME:
                        yomiFirstName = getValue();
                        break;
                    case Tags.CONTACTS_YOMI_LAST_NAME:
                        yomiLastName = getValue();
                        break;

                    case Tags.CONTACTS2_NICKNAME:
                        ops.addNickname(entity, getValue());
                        break;

                    case Tags.CONTACTS_ASSISTANT_NAME:
                        ops.addRelation(entity, Relation.TYPE_ASSISTANT, getValue());
                        break;
                    case Tags.CONTACTS2_MANAGER_NAME:
                        ops.addRelation(entity, Relation.TYPE_MANAGER, getValue());
                        break;
                    case Tags.CONTACTS_SPOUSE:
                        ops.addRelation(entity, Relation.TYPE_SPOUSE, getValue());
                        break;
                    case Tags.CONTACTS_DEPARTMENT:
                        department = getValue();
                        break;
                    case Tags.CONTACTS_TITLE:
                        prefix = getValue();
                        break;

                    // EAS Business
                    case Tags.CONTACTS_OFFICE_LOCATION:
                        officeLocation = getValue();
                        break;
                    case Tags.CONTACTS2_CUSTOMER_ID:
                        business.customerId = getValue();
                        break;
                    case Tags.CONTACTS2_GOVERNMENT_ID:
                        business.governmentId = getValue();
                        break;
                    case Tags.CONTACTS2_ACCOUNT_NAME:
                        business.accountName = getValue();
                        break;

                    // EAS Personal
                    case Tags.CONTACTS_ANNIVERSARY:
                        personal.anniversary = getValue();
                        break;
                    case Tags.CONTACTS_BIRTHDAY:
                        ops.addBirthday(entity, getValue());
                        break;
                    case Tags.CONTACTS_WEBPAGE:
                        ops.addWebpage(entity, getValue());
                        break;

                    case Tags.CONTACTS_PICTURE:
                        ops.addPhoto(entity, getValue());
                        break;

                    case Tags.BASE_BODY:
                        ops.addNote(entity, bodyParser());
                        break;
                    case Tags.CONTACTS_BODY:
                        ops.addNote(entity, getValue());
                        break;

                    case Tags.CONTACTS_CATEGORIES:
                        mGroupsUsed = true;
                        categoriesParser(ops, entity);
                        break;

                    case Tags.CONTACTS_COMPRESSED_RTF:
                        // We don't use this, and it isn't necessary to upload, so we'll ignore it
                        skipTag();
                        break;

                    default:
                        skipTag();
                }
            }

            // We must have first name, last name, or company name
            String name = null;
            if (firstName != null || lastName != null) {
                if (firstName == null) {
                    name = lastName;
                } else if (lastName == null) {
                    name = firstName;
                } else {
                    name = firstName + ' ' + lastName;
                }
            } else if (companyName != null) {
                name = companyName;
            }

            ops.addName(entity, prefix, firstName, lastName, middleName, suffix, name,
                    yomiFirstName, yomiLastName, fileAs);
            ops.addBusiness(entity, business);
            ops.addPersonal(entity, personal);

            ops.addUntyped(entity, emails, Email.CONTENT_ITEM_TYPE, -1, MAX_EMAIL_ROWS);
            ops.addUntyped(entity, ims, Im.CONTENT_ITEM_TYPE, -1, MAX_IM_ROWS);
            ops.addUntyped(entity, homePhones, Phone.CONTENT_ITEM_TYPE, Phone.TYPE_HOME,
                    MAX_PHONE_ROWS);
            ops.addUntyped(entity, workPhones, Phone.CONTENT_ITEM_TYPE, Phone.TYPE_WORK,
                    MAX_PHONE_ROWS);

            if (!children.isEmpty()) {
                ops.addChildren(entity, children);
            }

            if (work.hasData()) {
                ops.addPostal(entity, StructuredPostal.TYPE_WORK, work.street, work.city,
                        work.state, work.country, work.code);
            }
            if (home.hasData()) {
                ops.addPostal(entity, StructuredPostal.TYPE_HOME, home.street, home.city,
                        home.state, home.country, home.code);
            }
            if (other.hasData()) {
                ops.addPostal(entity, StructuredPostal.TYPE_OTHER, other.street, other.city,
                        other.state, other.country, other.code);
            }

            if (companyName != null) {
                ops.addOrganization(entity, Organization.TYPE_WORK, companyName, title, department,
                        yomiCompanyName, officeLocation);
            }

            if (entity != null) {
                // We've been removing rows from the list as they've been found in the xml
                // Any that are left must have been deleted on the server
                ArrayList<NamedContentValues> ncvList = entity.getSubValues();
                for (NamedContentValues ncv: ncvList) {
                    // These rows need to be deleted...
                    Uri u = dataUriFromNamedContentValues(ncv);
                    ops.add(ContentProviderOperation.newDelete(addCallerIsSyncAdapterParameter(u))
                            .build());
                }
            }
        }

        private void categoriesParser(ContactOperations ops, Entity entity) throws IOException {
            while (nextTag(Tags.CONTACTS_CATEGORIES) != END) {
                switch (tag) {
                    case Tags.CONTACTS_CATEGORY:
                        ops.addGroup(entity, getValue());
                        break;
                    default:
                        skipTag();
                }
            }
        }

        private void childrenParser(ArrayList<String> children) throws IOException {
            while (nextTag(Tags.CONTACTS_CHILDREN) != END) {
                switch (tag) {
                    case Tags.CONTACTS_CHILD:
                        if (children.size() < EasChildren.MAX_CHILDREN) {
                            children.add(getValue());
                        }
                        break;
                    default:
                        skipTag();
                }
            }
        }

        private String bodyParser() throws IOException {
            String body = null;
            while (nextTag(Tags.BASE_BODY) != END) {
                switch (tag) {
                    case Tags.BASE_DATA:
                        body = getValue();
                        break;
                    default:
                        skipTag();
                }
            }
            return body;
        }

        public void addParser(ContactOperations ops) throws IOException {
            String serverId = null;
            while (nextTag(Tags.SYNC_ADD) != END) {
                switch (tag) {
                    case Tags.SYNC_SERVER_ID: // same as
                        serverId = getValue();
                        break;
                    case Tags.SYNC_APPLICATION_DATA:
                        addData(serverId, ops, null);
                        break;
                    default:
                        skipTag();
                }
            }
        }

        private Cursor getServerIdCursor(String serverId) {
            mBindArgument[0] = serverId;
            return mContentResolver.query(mAccountUri, ID_PROJECTION, SERVER_ID_SELECTION,
                    mBindArgument, null);
        }

        private Cursor getClientIdCursor(String clientId) {
            mBindArgument[0] = clientId;
            return mContentResolver.query(mAccountUri, ID_PROJECTION, CLIENT_ID_SELECTION,
                    mBindArgument, null);
        }

        public void deleteParser(ContactOperations ops) throws IOException {
            while (nextTag(Tags.SYNC_DELETE) != END) {
                switch (tag) {
                    case Tags.SYNC_SERVER_ID:
                        String serverId = getValue();
                        // Find the message in this mailbox with the given serverId
                        Cursor c = getServerIdCursor(serverId);
                        try {
                            if (c.moveToFirst()) {
                                userLog("Deleting ", serverId);
                                ops.delete(c.getLong(0));
                            }
                        } finally {
                            c.close();
                        }
                        break;
                    default:
                        skipTag();
                }
            }
        }

        class ServerChange {
            long id;
            boolean read;

            ServerChange(long _id, boolean _read) {
                id = _id;
                read = _read;
            }
        }

        /**
         * Changes are handled row by row, and only changed/new rows are acted upon
         * @param ops the array of pending ContactProviderOperations.
         * @throws IOException
         */
        public void changeParser(ContactOperations ops) throws IOException {
            String serverId = null;
            Entity entity = null;
            while (nextTag(Tags.SYNC_CHANGE) != END) {
                switch (tag) {
                    case Tags.SYNC_SERVER_ID:
                        serverId = getValue();
                        Cursor c = getServerIdCursor(serverId);
                        try {
                            if (c.moveToFirst()) {
                                // TODO Handle deleted individual rows...
                                Uri uri = ContentUris.withAppendedId(
                                        RawContacts.CONTENT_URI, c.getLong(0));
                                uri = Uri.withAppendedPath(
                                        uri, RawContacts.Entity.CONTENT_DIRECTORY);
                                EntityIterator entityIterator = RawContacts.newEntityIterator(
                                    mContentResolver.query(uri, null, null, null, null));
                                if (entityIterator.hasNext()) {
                                    entity = entityIterator.next();
                                }
                                userLog("Changing contact ", serverId);
                            }
                        } finally {
                            c.close();
                        }
                        break;
                    case Tags.SYNC_APPLICATION_DATA:
                        addData(serverId, ops, entity);
                        break;
                    default:
                        skipTag();
                }
            }
        }

        @Override
        public void commandsParser() throws IOException {
            while (nextTag(Tags.SYNC_COMMANDS) != END) {
                if (tag == Tags.SYNC_ADD) {
                    addParser(ops);
                    incrementChangeCount();
                } else if (tag == Tags.SYNC_DELETE) {
                    deleteParser(ops);
                    incrementChangeCount();
                } else if (tag == Tags.SYNC_CHANGE) {
                    changeParser(ops);
                    incrementChangeCount();
                } else
                    skipTag();
            }
        }

        @Override
        public void commit() throws IOException {
           // Save the syncKey here, using the Helper provider by Contacts provider
            userLog("Contacts SyncKey saved as: ", mMailbox.mSyncKey);
            ops.add(SyncStateContract.Helpers.newSetOperation(SyncState.CONTENT_URI,
                    mAccountManagerAccount, mMailbox.mSyncKey.getBytes()));

            // Execute these all at once...
            ops.execute();

            if (ops.mResults != null) {
                ContentValues cv = new ContentValues();
                cv.put(RawContacts.DIRTY, 0);
                for (int i = 0; i < ops.mContactIndexCount; i++) {
                    int index = ops.mContactIndexArray[i];
                    Uri u = ops.mResults[index].uri;
                    if (u != null) {
                        String idString = u.getLastPathSegment();
                        mContentResolver.update(
                                addCallerIsSyncAdapterParameter(RawContacts.CONTENT_URI), cv,
                                RawContacts._ID + "=" + idString, null);
                    }
                }
            }
        }

        public void addResponsesParser() throws IOException {
            String serverId = null;
            String clientId = null;
            ContentValues cv = new ContentValues();
            while (nextTag(Tags.SYNC_ADD) != END) {
                switch (tag) {
                    case Tags.SYNC_SERVER_ID:
                        serverId = getValue();
                        break;
                    case Tags.SYNC_CLIENT_ID:
                        clientId = getValue();
                        break;
                    case Tags.SYNC_STATUS:
                        getValue();
                        break;
                    default:
                        skipTag();
                }
            }

            // This is theoretically impossible, but...
            if (clientId == null || serverId == null) return;

            Cursor c = getClientIdCursor(clientId);
            try {
                if (c.moveToFirst()) {
                    cv.put(RawContacts.SOURCE_ID, serverId);
                    cv.put(RawContacts.DIRTY, 0);
                    ops.add(ContentProviderOperation.newUpdate(
                            ContentUris.withAppendedId(
                                    addCallerIsSyncAdapterParameter(RawContacts.CONTENT_URI),
                                    c.getLong(0)))
                            .withValues(cv)
                            .build());
                    userLog("New contact " + clientId + " was given serverId: " + serverId);
                }
            } finally {
                c.close();
            }
        }

        public void changeResponsesParser() throws IOException {
            String serverId = null;
            String status = null;
            while (nextTag(Tags.SYNC_CHANGE) != END) {
                switch (tag) {
                    case Tags.SYNC_SERVER_ID:
                        serverId = getValue();
                        break;
                    case Tags.SYNC_STATUS:
                        status = getValue();
                        break;
                    default:
                        skipTag();
                }
            }
            if (serverId != null && status != null) {
                userLog("Changed contact " + serverId + " failed with status: " + status);
            }
        }


        @Override
        public void responsesParser() throws IOException {
            // Handle server responses here (for Add and Change)
            while (nextTag(Tags.SYNC_RESPONSES) != END) {
                if (tag == Tags.SYNC_ADD) {
                    addResponsesParser();
                } else if (tag == Tags.SYNC_CHANGE) {
                    changeResponsesParser();
                } else
                    skipTag();
            }
        }
    }


    private Uri uriWithAccountAndIsSyncAdapter(Uri uri) {
        return uri.buildUpon()
            .appendQueryParameter(RawContacts.ACCOUNT_NAME, mAccount.mEmailAddress)
            .appendQueryParameter(RawContacts.ACCOUNT_TYPE, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE)
            .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
            .build();
    }

    /**
     * SmartBuilder is a wrapper for the Builder class that is used to create/update rows for a
     * ContentProvider.  It has, in addition to the Builder, ContentValues which, if present,
     * represent the current values of that row, that can be compared against current values to
     * see whether an update is even necessary.  The methods on SmartBuilder are delegated to
     * the Builder.
     */
    private class RowBuilder {
        Builder builder;
        ContentValues cv;

        public RowBuilder(Builder _builder) {
            builder = _builder;
        }

        public RowBuilder(Builder _builder, NamedContentValues _ncv) {
            builder = _builder;
            cv = _ncv.values;
        }

        RowBuilder withValues(ContentValues values) {
            builder.withValues(values);
            return this;
        }

        RowBuilder withValueBackReference(String key, int previousResult) {
            builder.withValueBackReference(key, previousResult);
            return this;
        }

        ContentProviderOperation build() {
            return builder.build();
        }

        RowBuilder withValue(String key, Object value) {
            builder.withValue(key, value);
            return this;
        }
    }

    private class ContactOperations extends ArrayList<ContentProviderOperation> {
        private static final long serialVersionUID = 1L;
        private int mCount = 0;
        private int mContactBackValue = mCount;
        // Make an array big enough for the PIM window (max items we can get)
        private int[] mContactIndexArray =
            new int[Integer.parseInt(AbstractSyncAdapter.PIM_WINDOW_SIZE)];
        private int mContactIndexCount = 0;
        private ContentProviderResult[] mResults = null;

        @Override
        public boolean add(ContentProviderOperation op) {
            super.add(op);
            mCount++;
            return true;
        }

        public void newContact(String serverId) {
            Builder builder = ContentProviderOperation
                .newInsert(uriWithAccountAndIsSyncAdapter(RawContacts.CONTENT_URI));
            ContentValues values = new ContentValues();
            values.put(RawContacts.SOURCE_ID, serverId);
            builder.withValues(values);
            mContactBackValue = mCount;
            mContactIndexArray[mContactIndexCount++] = mCount;
            add(builder.build());
        }

        public void delete(long id) {
            add(ContentProviderOperation
                    .newDelete(ContentUris.withAppendedId(RawContacts.CONTENT_URI, id)
                            .buildUpon()
                            .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
                            .build())
                    .build());
        }

        public void execute() {
            synchronized (mService.getSynchronizer()) {
                if (!mService.isStopped()) {
                    try {
                        if (!isEmpty()) {
                            mService.userLog("Executing ", size(), " CPO's");
                            mResults = mContext.getContentResolver().applyBatch(
                                    ContactsContract.AUTHORITY, this);
                        }
                    } catch (RemoteException e) {
                        // There is nothing sensible to be done here
                        Log.e(TAG, "problem inserting contact during server update", e);
                    } catch (OperationApplicationException e) {
                        // There is nothing sensible to be done here
                        Log.e(TAG, "problem inserting contact during server update", e);
                    }
                }
            }
        }

        /**
         * Given the list of NamedContentValues for an entity, a mime type, and a subtype,
         * tries to find a match, returning it
         * @param list the list of NCV's from the contact entity
         * @param contentItemType the mime type we're looking for
         * @param type the subtype (e.g. HOME, WORK, etc.)
         * @return the matching NCV or null if not found
         */
        private NamedContentValues findTypedData(ArrayList<NamedContentValues> list,
                String contentItemType, int type, String stringType) {
            NamedContentValues result = null;

            // Loop through the ncv's, looking for an existing row
            for (NamedContentValues namedContentValues: list) {
                Uri uri = namedContentValues.uri;
                ContentValues cv = namedContentValues.values;
                if (Data.CONTENT_URI.equals(uri)) {
                    String mimeType = cv.getAsString(Data.MIMETYPE);
                    if (mimeType.equals(contentItemType)) {
                        if (stringType != null) {
                            if (cv.getAsString(GroupMembership.GROUP_ROW_ID).equals(stringType)) {
                                result = namedContentValues;
                            }
                        // Note Email.TYPE could be ANY type column; they are all defined in
                        // the private CommonColumns class in ContactsContract
                        // We'll accept either type < 0 (don't care), cv doesn't have a type,
                        // or the types are equal
                        } else if (type < 0 || !cv.containsKey(Email.TYPE) ||
                                cv.getAsInteger(Email.TYPE) == type) {
                            result = namedContentValues;
                        }
                    }
                }
            }

            // If we've found an existing data row, we'll delete it.  Any rows left at the
            // end should be deleted...
            if (result != null) {
                list.remove(result);
            }

            // Return the row found (or null)
            return result;
        }

        /**
         * Given the list of NamedContentValues for an entity and a mime type
         * gather all of the matching NCV's, returning them
         * @param list the list of NCV's from the contact entity
         * @param contentItemType the mime type we're looking for
         * @param type the subtype (e.g. HOME, WORK, etc.)
         * @return the matching NCVs
         */
        private ArrayList<NamedContentValues> findUntypedData(ArrayList<NamedContentValues> list,
                int type, String contentItemType) {
            ArrayList<NamedContentValues> result = new ArrayList<NamedContentValues>();

            // Loop through the ncv's, looking for an existing row
            for (NamedContentValues namedContentValues: list) {
                Uri uri = namedContentValues.uri;
                ContentValues cv = namedContentValues.values;
                if (Data.CONTENT_URI.equals(uri)) {
                    String mimeType = cv.getAsString(Data.MIMETYPE);
                    if (mimeType.equals(contentItemType)) {
                        if (type != -1) {
                            int subtype = cv.getAsInteger(Phone.TYPE);
                            if (type != subtype) {
                                continue;
                            }
                        }
                        result.add(namedContentValues);
                    }
                }
            }

            // If we've found an existing data row, we'll delete it.  Any rows left at the
            // end should be deleted...
            for (NamedContentValues values : result) {
                list.remove(values);
            }

            // Return the row found (or null)
            return result;
        }

        /**
         * Create a wrapper for a builder (insert or update) that also includes the NCV for
         * an existing row of this type.   If the SmartBuilder's cv field is not null, then
         * it represents the current (old) values of this field.  The caller can then check
         * whether the field is now different and needs to be updated; if it's not different,
         * the caller will simply return and not generate a new CPO.  Otherwise, the builder
         * should have its content values set, and the built CPO should be added to the
         * ContactOperations list.
         *
         * @param entity the contact entity (or null if this is a new contact)
         * @param mimeType the mime type of this row
         * @param type the subtype of this row
         * @param stringType for groups, the name of the group (type will be ignored), or null
         * @return the created SmartBuilder
         */
        public RowBuilder createBuilder(Entity entity, String mimeType, int type,
                String stringType) {
            RowBuilder builder = null;

            if (entity != null) {
                NamedContentValues ncv =
                    findTypedData(entity.getSubValues(), mimeType, type, stringType);
                if (ncv != null) {
                    builder = new RowBuilder(
                            ContentProviderOperation
                                .newUpdate(addCallerIsSyncAdapterParameter(
                                    dataUriFromNamedContentValues(ncv))),
                            ncv);
                }
            }

            if (builder == null) {
                builder = newRowBuilder(entity, mimeType);
            }

            // Return the appropriate builder (insert or update)
            // Caller will fill in the appropriate values; 4 MIMETYPE is already set
            return builder;
        }

        private RowBuilder typedRowBuilder(Entity entity, String mimeType, int type) {
            return createBuilder(entity, mimeType, type, null);
        }

        private RowBuilder untypedRowBuilder(Entity entity, String mimeType) {
            return createBuilder(entity, mimeType, -1, null);
        }

        private RowBuilder newRowBuilder(Entity entity, String mimeType) {
            // This is a new row; first get the contactId
            // If the Contact is new, use the saved back value; otherwise the value in the entity
            int contactId = mContactBackValue;
            if (entity != null) {
                contactId = entity.getEntityValues().getAsInteger(RawContacts._ID);
            }

            // Create an insert operation with the proper contactId reference
            RowBuilder builder =
                new RowBuilder(ContentProviderOperation.newInsert(
                        addCallerIsSyncAdapterParameter(Data.CONTENT_URI)));
            if (entity == null) {
                builder.withValueBackReference(Data.RAW_CONTACT_ID, contactId);
            } else {
                builder.withValue(Data.RAW_CONTACT_ID, contactId);
            }

            // Set the mime type of the row
            builder.withValue(Data.MIMETYPE, mimeType);
            return builder;
        }

        /**
         * Compare a column in a ContentValues with an (old) value, and see if they are the
         * same.  For this purpose, null and an empty string are considered the same.
         * @param cv a ContentValues object, from a NamedContentValues
         * @param column a column that might be in the ContentValues
         * @param oldValue an old value (or null) to check against
         * @return whether the column's value in the ContentValues matches oldValue
         */
        private boolean cvCompareString(ContentValues cv, String column, String oldValue) {
            if (cv.containsKey(column)) {
                if (oldValue != null && cv.getAsString(column).equals(oldValue)) {
                    return true;
                }
            } else if (oldValue == null || oldValue.length() == 0) {
                return true;
            }
            return false;
        }

        public void addChildren(Entity entity, ArrayList<String> children) {
            RowBuilder builder = untypedRowBuilder(entity, EasChildren.CONTENT_ITEM_TYPE);
            int i = 0;
            for (String child: children) {
                builder.withValue(EasChildren.ROWS[i++], child);
            }
            add(builder.build());
        }

        public void addGroup(Entity entity, String group) {
            RowBuilder builder =
                createBuilder(entity, GroupMembership.CONTENT_ITEM_TYPE, -1, group);
            builder.withValue(GroupMembership.GROUP_SOURCE_ID, group);
            add(builder.build());
        }

        public void addBirthday(Entity entity, String birthday) {
            RowBuilder builder =
                    typedRowBuilder(entity, Event.CONTENT_ITEM_TYPE, Event.TYPE_BIRTHDAY);
            ContentValues cv = builder.cv;
            if (cv != null && cvCompareString(cv, Event.START_DATE, birthday)) {
                return;
            }
            builder.withValue(Event.START_DATE, birthday);
            builder.withValue(Event.TYPE, Event.TYPE_BIRTHDAY);
            add(builder.build());
        }

        public void addName(Entity entity, String prefix, String givenName, String familyName,
                String middleName, String suffix, String displayName, String yomiFirstName,
                String yomiLastName, String fileAs) {
            RowBuilder builder = untypedRowBuilder(entity, StructuredName.CONTENT_ITEM_TYPE);
            ContentValues cv = builder.cv;
            if (cv != null && cvCompareString(cv, StructuredName.GIVEN_NAME, givenName) &&
                    cvCompareString(cv, StructuredName.FAMILY_NAME, familyName) &&
                    cvCompareString(cv, StructuredName.MIDDLE_NAME, middleName) &&
                    cvCompareString(cv, StructuredName.PREFIX, prefix) &&
                    cvCompareString(cv, StructuredName.PHONETIC_GIVEN_NAME, yomiFirstName) &&
                    cvCompareString(cv, StructuredName.PHONETIC_FAMILY_NAME, yomiLastName) &&
                    //cvCompareString(cv, StructuredName.DISPLAY_NAME, fileAs) &&
                    cvCompareString(cv, StructuredName.SUFFIX, suffix)) {
                return;
            }
            builder.withValue(StructuredName.GIVEN_NAME, givenName);
            builder.withValue(StructuredName.FAMILY_NAME, familyName);
            builder.withValue(StructuredName.MIDDLE_NAME, middleName);
            builder.withValue(StructuredName.SUFFIX, suffix);
            builder.withValue(StructuredName.PHONETIC_GIVEN_NAME, yomiFirstName);
            builder.withValue(StructuredName.PHONETIC_FAMILY_NAME, yomiLastName);
            builder.withValue(StructuredName.PREFIX, prefix);
            //builder.withValue(StructuredName.DISPLAY_NAME, fileAs);
            add(builder.build());
        }

        public void addPersonal(Entity entity, EasPersonal personal) {
            RowBuilder builder = untypedRowBuilder(entity, EasPersonal.CONTENT_ITEM_TYPE);
            ContentValues cv = builder.cv;
            if (cv != null && cvCompareString(cv, EasPersonal.ANNIVERSARY, personal.anniversary) &&
                    cvCompareString(cv, EasPersonal.FILE_AS , personal.fileAs)) {
                return;
            }
            if (!personal.hasData()) {
                return;
            }
            builder.withValue(EasPersonal.FILE_AS, personal.fileAs);
            builder.withValue(EasPersonal.ANNIVERSARY, personal.anniversary);
            add(builder.build());
        }

        public void addBusiness(Entity entity, EasBusiness business) {
            RowBuilder builder = untypedRowBuilder(entity, EasBusiness.CONTENT_ITEM_TYPE);
            ContentValues cv = builder.cv;
            if (cv != null && cvCompareString(cv, EasBusiness.ACCOUNT_NAME, business.accountName) &&
                    cvCompareString(cv, EasBusiness.CUSTOMER_ID, business.customerId) &&
                    cvCompareString(cv, EasBusiness.GOVERNMENT_ID, business.governmentId)) {
                return;
            }
            if (!business.hasData()) {
                return;
            }
            builder.withValue(EasBusiness.ACCOUNT_NAME, business.accountName);
            builder.withValue(EasBusiness.CUSTOMER_ID, business.customerId);
            builder.withValue(EasBusiness.GOVERNMENT_ID, business.governmentId);
            add(builder.build());
        }

        public void addPhoto(Entity entity, String photo) {
            RowBuilder builder = untypedRowBuilder(entity, Photo.CONTENT_ITEM_TYPE);
            // We're always going to add this; it's not worth trying to figure out whether the
            // picture is the same as the one stored.
            byte[] pic = Base64.decode(photo, Base64.DEFAULT);
            builder.withValue(Photo.PHOTO, pic);
            add(builder.build());
        }

        public void addPhone(Entity entity, int type, String phone) {
            RowBuilder builder = typedRowBuilder(entity, Phone.CONTENT_ITEM_TYPE, type);
            ContentValues cv = builder.cv;
            if (cv != null && cvCompareString(cv, Phone.NUMBER, phone)) {
                return;
            }
            builder.withValue(Phone.TYPE, type);
            builder.withValue(Phone.NUMBER, phone);
            add(builder.build());
        }

        public void addWebpage(Entity entity, String url) {
            RowBuilder builder = untypedRowBuilder(entity, Website.CONTENT_ITEM_TYPE);
            ContentValues cv = builder.cv;
            if (cv != null && cvCompareString(cv, Website.URL, url)) {
                return;
            }
            builder.withValue(Website.TYPE, Website.TYPE_WORK);
            builder.withValue(Website.URL, url);
            add(builder.build());
        }

        public void addRelation(Entity entity, int type, String value) {
            RowBuilder builder = typedRowBuilder(entity, Relation.CONTENT_ITEM_TYPE, type);
            ContentValues cv = builder.cv;
            if (cv != null && cvCompareString(cv, Relation.DATA, value)) {
                return;
            }
            builder.withValue(Relation.TYPE, type);
            builder.withValue(Relation.DATA, value);
            add(builder.build());
        }

        public void addNickname(Entity entity, String name) {
            RowBuilder builder =
                typedRowBuilder(entity, Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE_DEFAULT);
            ContentValues cv = builder.cv;
            if (cv != null && cvCompareString(cv, Nickname.NAME, name)) {
                return;
            }
            builder.withValue(Nickname.TYPE, Nickname.TYPE_DEFAULT);
            builder.withValue(Nickname.NAME, name);
            add(builder.build());
        }

        public void addPostal(Entity entity, int type, String street, String city, String state,
                String country, String code) {
            RowBuilder builder = typedRowBuilder(entity, StructuredPostal.CONTENT_ITEM_TYPE,
                    type);
            ContentValues cv = builder.cv;
            if (cv != null && cvCompareString(cv, StructuredPostal.CITY, city) &&
                    cvCompareString(cv, StructuredPostal.STREET, street) &&
                    cvCompareString(cv, StructuredPostal.COUNTRY, country) &&
                    cvCompareString(cv, StructuredPostal.POSTCODE, code) &&
                    cvCompareString(cv, StructuredPostal.REGION, state)) {
                return;
            }
            builder.withValue(StructuredPostal.TYPE, type);
            builder.withValue(StructuredPostal.CITY, city);
            builder.withValue(StructuredPostal.STREET, street);
            builder.withValue(StructuredPostal.COUNTRY, country);
            builder.withValue(StructuredPostal.POSTCODE, code);
            builder.withValue(StructuredPostal.REGION, state);
            add(builder.build());
        }

       /**
         * We now are dealing with up to maxRows typeless rows of mimeType data.  We need to try to
         * match them with existing rows; if there's a match, everything's great.  Otherwise, we
         * either need to add a new row for the data, or we have to replace an existing one
         * that no longer matches.  This is similar to the way Emails are handled.
         */
        public void addUntyped(Entity entity, ArrayList<UntypedRow> rows, String mimeType,
                int type, int maxRows) {
            // Make a list of all same type rows in the existing entity
            ArrayList<NamedContentValues> oldValues = EMPTY_ARRAY_NAMEDCONTENTVALUES;
            ArrayList<NamedContentValues> entityValues = EMPTY_ARRAY_NAMEDCONTENTVALUES;
            if (entity != null) {
                oldValues = findUntypedData(entityValues, type, mimeType);
                entityValues = entity.getSubValues();
            }

            // These will be rows needing replacement with new values
            ArrayList<UntypedRow> rowsToReplace = new ArrayList<UntypedRow>();

            // The count of existing rows
            int numRows = oldValues.size();
            for (UntypedRow row: rows) {
                boolean found = false;
                // If we already have this row, mark it
                for (NamedContentValues ncv: oldValues) {
                    ContentValues cv = ncv.values;
                    String data = cv.getAsString(COMMON_DATA_ROW);
                    int rowType = -1;
                    if (cv.containsKey(COMMON_TYPE_ROW)) {
                        rowType = cv.getAsInteger(COMMON_TYPE_ROW);
                    }
                    if (row.isSameAs(rowType, data)) {
                        cv.put(FOUND_DATA_ROW, true);
                        // Remove this to indicate it's still being used
                        entityValues.remove(ncv);
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    // If we don't, there are two possibilities
                    if (numRows < maxRows) {
                        // If there are available rows, add a new one
                        RowBuilder builder = newRowBuilder(entity, mimeType);
                        row.addValues(builder);
                        add(builder.build());
                        numRows++;
                    } else {
                        // Otherwise, say we need to replace a row with this
                        rowsToReplace.add(row);
                    }
                }
            }

            // Go through rows needing replacement
            for (UntypedRow row: rowsToReplace) {
                for (NamedContentValues ncv: oldValues) {
                    ContentValues cv = ncv.values;
                    // Find a row that hasn't been used (i.e. doesn't match current rows)
                    if (!cv.containsKey(FOUND_DATA_ROW)) {
                        // And update it
                        RowBuilder builder = new RowBuilder(
                                ContentProviderOperation
                                    .newUpdate(addCallerIsSyncAdapterParameter(
                                        dataUriFromNamedContentValues(ncv))),
                                ncv);
                        row.addValues(builder);
                        add(builder.build());
                    }
                }
            }
        }

        public void addOrganization(Entity entity, int type, String company, String title,
                String department, String yomiCompanyName, String officeLocation) {
            RowBuilder builder = typedRowBuilder(entity, Organization.CONTENT_ITEM_TYPE, type);
            ContentValues cv = builder.cv;
            if (cv != null && cvCompareString(cv, Organization.COMPANY, company) &&
                    cvCompareString(cv, Organization.PHONETIC_NAME, yomiCompanyName) &&
                    cvCompareString(cv, Organization.DEPARTMENT, department) &&
                    cvCompareString(cv, Organization.TITLE, title) &&
                    cvCompareString(cv, Organization.OFFICE_LOCATION, officeLocation)) {
                return;
            }
            builder.withValue(Organization.TYPE, type);
            builder.withValue(Organization.COMPANY, company);
            builder.withValue(Organization.TITLE, title);
            builder.withValue(Organization.DEPARTMENT, department);
            builder.withValue(Organization.PHONETIC_NAME, yomiCompanyName);
            builder.withValue(Organization.OFFICE_LOCATION, officeLocation);
            add(builder.build());
        }

        public void addNote(Entity entity, String note) {
            RowBuilder builder = typedRowBuilder(entity, Note.CONTENT_ITEM_TYPE, -1);
            ContentValues cv = builder.cv;
            if (note == null) return;
            note = note.replaceAll("\r\n", "\n");
            if (cv != null && cvCompareString(cv, Note.NOTE, note)) {
                return;
            }

            // Reject notes with nothing in them.  Often, we get something from Outlook when
            // nothing was ever entered.  Sigh.
            int len = note.length();
            int i = 0;
            for (; i < len; i++) {
                char c = note.charAt(i);
                if (!Character.isWhitespace(c)) {
                    break;
                }
            }
            if (i == len) return;

            builder.withValue(Note.NOTE, note);
            add(builder.build());
        }
    }

    /**
     * Generate the uri for the data row associated with this NamedContentValues object
     * @param ncv the NamedContentValues object
     * @return a uri that can be used to refer to this row
     */
    public Uri dataUriFromNamedContentValues(NamedContentValues ncv) {
        long id = ncv.values.getAsLong(RawContacts._ID);
        Uri dataUri = ContentUris.withAppendedId(ncv.uri, id);
        return dataUri;
    }

    @Override
    public void cleanup() {
        // Mark the changed contacts dirty = 0
        // Permanently delete the user deletions
        ContactOperations ops = new ContactOperations();
        for (Long id: mUpdatedIdList) {
            ops.add(ContentProviderOperation
                    .newUpdate(ContentUris.withAppendedId(RawContacts.CONTENT_URI, id)
                            .buildUpon()
                            .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
                            .build())
                    .withValue(RawContacts.DIRTY, 0).build());
        }
        for (Long id: mDeletedIdList) {
            ops.add(ContentProviderOperation
                    .newDelete(ContentUris.withAppendedId(RawContacts.CONTENT_URI, id)
                            .buildUpon()
                            .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
                            .build())
                    .build());
        }
        ops.execute();
        ContentResolver cr = mContext.getContentResolver();
        if (mGroupsUsed) {
            // Make sure the title column is set for all of our groups
            // And that all of our groups are visible
            // TODO Perhaps the visible part should only happen when the group is created, but
            // this is fine for now.
            Uri groupsUri = uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI);
            Cursor c = cr.query(groupsUri, new String[] {Groups.SOURCE_ID, Groups.TITLE},
                    Groups.TITLE + " IS NULL", null, null);
            ContentValues values = new ContentValues();
            values.put(Groups.GROUP_VISIBLE, 1);
            try {
                while (c.moveToNext()) {
                    String sourceId = c.getString(0);
                    values.put(Groups.TITLE, sourceId);
                    cr.update(uriWithAccountAndIsSyncAdapter(groupsUri), values,
                            Groups.SOURCE_ID + "=?", new String[] {sourceId});
                }
            } finally {
                c.close();
            }
        }
    }

    @Override
    public String getCollectionName() {
        return "Contacts";
    }

    private void sendEmail(Serializer s, ContentValues cv, int count, String displayName)
            throws IOException {
        // Get both parts of the email address (a newly created one in the UI won't have a name)
        String addr = cv.getAsString(Email.DATA);
        String name = cv.getAsString(Email.DISPLAY_NAME);
        if (name == null) {
            if (displayName != null) {
                name = displayName;
            } else {
                name = addr;
            }
        }
        // Compose address from name and addr
        if (addr != null) {
            String value;
            // Only send the raw email address for EAS 2.5 (Hotmail, in particular, chokes on
            // an RFC822 address)
            if (mService.mProtocolVersionDouble < Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
                value = addr;
            } else {
                value = '\"' + name + "\" <" + addr + '>';
            }
            if (count < MAX_EMAIL_ROWS) {
                s.data(EMAIL_TAGS[count], value);
            }
        }
    }

    private void sendIm(Serializer s, ContentValues cv, int count) throws IOException {
        String value = cv.getAsString(Im.DATA);
        if (value == null) return;
        if (count < MAX_IM_ROWS) {
            s.data(IM_TAGS[count], value);
        }
    }

    private void sendOnePostal(Serializer s, ContentValues cv, int[] fieldNames)
            throws IOException{
        sendStringData(s, cv, StructuredPostal.CITY, fieldNames[0]);
        sendStringData(s, cv, StructuredPostal.COUNTRY, fieldNames[1]);
        sendStringData(s, cv, StructuredPostal.POSTCODE, fieldNames[2]);
        sendStringData(s, cv, StructuredPostal.REGION, fieldNames[3]);
        sendStringData(s, cv, StructuredPostal.STREET, fieldNames[4]);
    }

    private void sendStructuredPostal(Serializer s, ContentValues cv) throws IOException {
        switch (cv.getAsInteger(StructuredPostal.TYPE)) {
            case StructuredPostal.TYPE_HOME:
                sendOnePostal(s, cv, HOME_ADDRESS_TAGS);
                break;
            case StructuredPostal.TYPE_WORK:
                sendOnePostal(s, cv, WORK_ADDRESS_TAGS);
                break;
            case StructuredPostal.TYPE_OTHER:
                sendOnePostal(s, cv, OTHER_ADDRESS_TAGS);
                break;
            default:
                break;
        }
    }

    private void sendStringData(Serializer s, ContentValues cv, String column, int tag)
            throws IOException {
        if (cv.containsKey(column)) {
            String value = cv.getAsString(column);
            if (!TextUtils.isEmpty(value)) {
                s.data(tag, value);
            }
        }
    }

    private String sendStructuredName(Serializer s, ContentValues cv) throws IOException {
        String displayName = null;
        sendStringData(s, cv, StructuredName.FAMILY_NAME, Tags.CONTACTS_LAST_NAME);
        sendStringData(s, cv, StructuredName.GIVEN_NAME, Tags.CONTACTS_FIRST_NAME);
        sendStringData(s, cv, StructuredName.MIDDLE_NAME, Tags.CONTACTS_MIDDLE_NAME);
        sendStringData(s, cv, StructuredName.SUFFIX, Tags.CONTACTS_SUFFIX);
        sendStringData(s, cv, StructuredName.PHONETIC_GIVEN_NAME, Tags.CONTACTS_YOMI_FIRST_NAME);
        sendStringData(s, cv, StructuredName.PHONETIC_FAMILY_NAME, Tags.CONTACTS_YOMI_LAST_NAME);
        sendStringData(s, cv, StructuredName.PREFIX, Tags.CONTACTS_TITLE);
        if (cv.containsKey(StructuredName.DISPLAY_NAME)) {
            displayName = cv.getAsString(StructuredName.DISPLAY_NAME);
            if (!TextUtils.isEmpty(displayName)) {
                s.data(Tags.CONTACTS_FILE_AS, displayName);
            }
        }
        return displayName;
    }

    private void sendBusiness(Serializer s, ContentValues cv) throws IOException {
        sendStringData(s, cv, EasBusiness.ACCOUNT_NAME, Tags.CONTACTS2_ACCOUNT_NAME);
        sendStringData(s, cv, EasBusiness.CUSTOMER_ID, Tags.CONTACTS2_CUSTOMER_ID);
        sendStringData(s, cv, EasBusiness.GOVERNMENT_ID, Tags.CONTACTS2_GOVERNMENT_ID);
    }

    private void sendPersonal(Serializer s, ContentValues cv) throws IOException {
        sendStringData(s, cv, EasPersonal.ANNIVERSARY, Tags.CONTACTS_ANNIVERSARY);
        sendStringData(s, cv, EasPersonal.FILE_AS, Tags.CONTACTS_FILE_AS);
    }

    private void sendBirthday(Serializer s, ContentValues cv) throws IOException {
        sendStringData(s, cv, Event.START_DATE, Tags.CONTACTS_BIRTHDAY);
    }

    private void sendPhoto(Serializer s, ContentValues cv) throws IOException {
        if (cv.containsKey(Photo.PHOTO)) {
            byte[] bytes = cv.getAsByteArray(Photo.PHOTO);
            String pic = Base64.encodeToString(bytes, Base64.NO_WRAP);
            s.data(Tags.CONTACTS_PICTURE, pic);
        } else {
            // Send an empty tag, which signals the server to delete any pre-existing photo
            s.tag(Tags.CONTACTS_PICTURE);
        }
    }

    private void sendOrganization(Serializer s, ContentValues cv) throws IOException {
        sendStringData(s, cv, Organization.TITLE, Tags.CONTACTS_JOB_TITLE);
        sendStringData(s, cv, Organization.COMPANY, Tags.CONTACTS_COMPANY_NAME);
        sendStringData(s, cv, Organization.DEPARTMENT, Tags.CONTACTS_DEPARTMENT);
        sendStringData(s, cv, Organization.OFFICE_LOCATION, Tags.CONTACTS_OFFICE_LOCATION);
    }

    private void sendNickname(Serializer s, ContentValues cv) throws IOException {
        sendStringData(s, cv, Nickname.NAME, Tags.CONTACTS2_NICKNAME);
    }

    private void sendWebpage(Serializer s, ContentValues cv) throws IOException {
        sendStringData(s, cv, Website.URL, Tags.CONTACTS_WEBPAGE);
    }

    private void sendNote(Serializer s, ContentValues cv) throws IOException {
        // Even when there is no local note, we must explicitly upsync an empty note,
        // which is the only way to force the server to delete any pre-existing note.
        String note = "";
        if (cv.containsKey(Note.NOTE)) {
            // EAS won't accept note data with raw newline characters
            note = cv.getAsString(Note.NOTE).replaceAll("\n", "\r\n");
        }
        // Format of upsync data depends on protocol version
        if (mService.mProtocolVersionDouble >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
            s.start(Tags.BASE_BODY);
            s.data(Tags.BASE_TYPE, Eas.BODY_PREFERENCE_TEXT).data(Tags.BASE_DATA, note);
            s.end();
        } else {
            s.data(Tags.CONTACTS_BODY, note);
        }
    }

    private void sendChildren(Serializer s, ContentValues cv) throws IOException {
        boolean first = true;
        for (int i = 0; i < EasChildren.MAX_CHILDREN; i++) {
            String row = EasChildren.ROWS[i];
            if (cv.containsKey(row)) {
                if (first) {
                    s.start(Tags.CONTACTS_CHILDREN);
                    first = false;
                }
                s.data(Tags.CONTACTS_CHILD, cv.getAsString(row));
            }
        }
        if (!first) {
            s.end();
        }
    }

    private void sendPhone(Serializer s, ContentValues cv, int workCount, int homeCount)
            throws IOException {
        String value = cv.getAsString(Phone.NUMBER);
        if (value == null) return;
        switch (cv.getAsInteger(Phone.TYPE)) {
            case Phone.TYPE_WORK:
                if (workCount < MAX_PHONE_ROWS) {
                    s.data(WORK_PHONE_TAGS[workCount], value);
                }
                break;
            case Phone.TYPE_MMS:
                s.data(Tags.CONTACTS2_MMS, value);
                break;
            case Phone.TYPE_ASSISTANT:
                s.data(Tags.CONTACTS_ASSISTANT_TELEPHONE_NUMBER, value);
                break;
            case Phone.TYPE_FAX_WORK:
                s.data(Tags.CONTACTS_BUSINESS_FAX_NUMBER, value);
                break;
            case Phone.TYPE_COMPANY_MAIN:
                s.data(Tags.CONTACTS2_COMPANY_MAIN_PHONE, value);
                break;
            case Phone.TYPE_HOME:
                if (homeCount < MAX_PHONE_ROWS) {
                    s.data(HOME_PHONE_TAGS[homeCount], value);
                }
                break;
            case Phone.TYPE_MOBILE:
                s.data(Tags.CONTACTS_MOBILE_TELEPHONE_NUMBER, value);
                break;
            case Phone.TYPE_CAR:
                s.data(Tags.CONTACTS_CAR_TELEPHONE_NUMBER, value);
                break;
            case Phone.TYPE_PAGER:
                s.data(Tags.CONTACTS_PAGER_NUMBER, value);
                break;
            case Phone.TYPE_RADIO:
                s.data(Tags.CONTACTS_RADIO_TELEPHONE_NUMBER, value);
                break;
            case Phone.TYPE_FAX_HOME:
                s.data(Tags.CONTACTS_HOME_FAX_NUMBER, value);
                break;
            default:
                break;
        }
    }

    private void sendRelation(Serializer s, ContentValues cv) throws IOException {
        String value = cv.getAsString(Relation.DATA);
        if (value == null) return;
        switch (cv.getAsInteger(Relation.TYPE)) {
            case Relation.TYPE_ASSISTANT:
                s.data(Tags.CONTACTS_ASSISTANT_NAME, value);
                break;
            case Relation.TYPE_MANAGER:
                s.data(Tags.CONTACTS2_MANAGER_NAME, value);
                break;
            case Relation.TYPE_SPOUSE:
                s.data(Tags.CONTACTS_SPOUSE, value);
                break;
            default:
                break;
        }
    }

    private void dirtyContactsWithinDirtyGroups() {
        ContentResolver cr = mService.mContentResolver;
        Cursor c = cr.query(uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI),
                GROUPS_ID_PROJECTION, Groups.DIRTY + "=1", null, null);
        try {
            if (c.getCount() > 0) {
                String[] updateArgs = new String[1];
                ContentValues updateValues = new ContentValues();
                while (c.moveToNext()) {
                    // For each, "touch" all data rows with this group id; this will mark contacts
                    // in this group as dirty (per ContactsContract).  We will then know to upload
                    // them to the server with the modified group information
                    long id = c.getLong(0);
                    updateValues.put(GroupMembership.GROUP_ROW_ID, id);
                    updateArgs[0] = Long.toString(id);
                    cr.update(Data.CONTENT_URI, updateValues,
                            MIMETYPE_GROUP_MEMBERSHIP_AND_ID_EQUALS, updateArgs);
                }
                // Really delete groups that are marked deleted
                cr.delete(uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI), Groups.DELETED + "=1",
                        null);
                // Clear the dirty flag for all of our groups
                updateValues.clear();
                updateValues.put(Groups.DIRTY, 0);
                cr.update(uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI), updateValues, null,
                        null);
            }
        } finally {
            c.close();
        }
    }

    @Override
    public boolean sendLocalChanges(Serializer s) throws IOException {
        ContentResolver cr = mService.mContentResolver;

        // Find any groups of ours that are dirty and dirty those groups' members
        dirtyContactsWithinDirtyGroups();

        // First, let's find Contacts that have changed.
        Uri uri = uriWithAccountAndIsSyncAdapter(RawContactsEntity.CONTENT_URI);
        if (getSyncKey().equals("0")) {
            return false;
        }

        // Get them all atomically
        EntityIterator ei = RawContacts.newEntityIterator(
                cr.query(uri, null, RawContacts.DIRTY + "=1", null, null));
        ContentValues cidValues = new ContentValues();
        try {
            boolean first = true;
            final Uri rawContactUri = addCallerIsSyncAdapterParameter(RawContacts.CONTENT_URI);
            while (ei.hasNext()) {
                Entity entity = ei.next();
                // For each of these entities, create the change commands
                ContentValues entityValues = entity.getEntityValues();
                String serverId = entityValues.getAsString(RawContacts.SOURCE_ID);
                ArrayList<Integer> groupIds = new ArrayList<Integer>();
                if (first) {
                    s.start(Tags.SYNC_COMMANDS);
                    userLog("Sending Contacts changes to the server");
                    first = false;
                }
                if (serverId == null) {
                    // This is a new contact; create a clientId
                    String clientId = "new_" + mMailbox.mId + '_' + System.currentTimeMillis();
                    userLog("Creating new contact with clientId: ", clientId);
                    s.start(Tags.SYNC_ADD).data(Tags.SYNC_CLIENT_ID, clientId);
                    // And save it in the raw contact
                    cidValues.put(RawContacts.SYNC1, clientId);
                    cr.update(ContentUris.
                            withAppendedId(rawContactUri,
                                    entityValues.getAsLong(RawContacts._ID)),
                                    cidValues, null, null);
                } else {
                    if (entityValues.getAsInteger(RawContacts.DELETED) == 1) {
                        userLog("Deleting contact with serverId: ", serverId);
                        s.start(Tags.SYNC_DELETE).data(Tags.SYNC_SERVER_ID, serverId).end();
                        mDeletedIdList.add(entityValues.getAsLong(RawContacts._ID));
                        continue;
                    }
                    userLog("Upsync change to contact with serverId: " + serverId);
                    s.start(Tags.SYNC_CHANGE).data(Tags.SYNC_SERVER_ID, serverId);
                }
                s.start(Tags.SYNC_APPLICATION_DATA);
                // Write out the data here
                int imCount = 0;
                int emailCount = 0;
                int homePhoneCount = 0;
                int workPhoneCount = 0;
                String displayName = null;
                ArrayList<ContentValues> emailValues = new ArrayList<ContentValues>();
                for (NamedContentValues ncv: entity.getSubValues()) {
                    ContentValues cv = ncv.values;
                    String mimeType = cv.getAsString(Data.MIMETYPE);
                    if (mimeType.equals(Email.CONTENT_ITEM_TYPE)) {
                        emailValues.add(cv);
                    } else if (mimeType.equals(Nickname.CONTENT_ITEM_TYPE)) {
                        sendNickname(s, cv);
                    } else if (mimeType.equals(EasChildren.CONTENT_ITEM_TYPE)) {
                        sendChildren(s, cv);
                    } else if (mimeType.equals(EasBusiness.CONTENT_ITEM_TYPE)) {
                        sendBusiness(s, cv);
                    } else if (mimeType.equals(Website.CONTENT_ITEM_TYPE)) {
                        sendWebpage(s, cv);
                    } else if (mimeType.equals(EasPersonal.CONTENT_ITEM_TYPE)) {
                        sendPersonal(s, cv);
                    } else if (mimeType.equals(Phone.CONTENT_ITEM_TYPE)) {
                        sendPhone(s, cv, workPhoneCount, homePhoneCount);
                        int type = cv.getAsInteger(Phone.TYPE);
                        if (type == Phone.TYPE_HOME) homePhoneCount++;
                        if (type == Phone.TYPE_WORK) workPhoneCount++;
                    } else if (mimeType.equals(Relation.CONTENT_ITEM_TYPE)) {
                        sendRelation(s, cv);
                    } else if (mimeType.equals(StructuredName.CONTENT_ITEM_TYPE)) {
                        displayName = sendStructuredName(s, cv);
                    } else if (mimeType.equals(StructuredPostal.CONTENT_ITEM_TYPE)) {
                        sendStructuredPostal(s, cv);
                    } else if (mimeType.equals(Organization.CONTENT_ITEM_TYPE)) {
                        sendOrganization(s, cv);
                    } else if (mimeType.equals(Im.CONTENT_ITEM_TYPE)) {
                        sendIm(s, cv, imCount++);
                    } else if (mimeType.equals(Event.CONTENT_ITEM_TYPE)) {
                        Integer eventType = cv.getAsInteger(Event.TYPE);
                        if (eventType != null && eventType.equals(Event.TYPE_BIRTHDAY)) {
                            sendBirthday(s, cv);
                        }
                    } else if (mimeType.equals(GroupMembership.CONTENT_ITEM_TYPE)) {
                        // We must gather these, and send them together (below)
                        groupIds.add(cv.getAsInteger(GroupMembership.GROUP_ROW_ID));
                    } else if (mimeType.equals(Note.CONTENT_ITEM_TYPE)) {
                        sendNote(s, cv);
                    } else if (mimeType.equals(Photo.CONTENT_ITEM_TYPE)) {
                        sendPhoto(s, cv);
                    } else {
                        userLog("Contacts upsync, unknown data: ", mimeType);
                    }
                }

                // We do the email rows last, because we need to make sure we've found the
                // displayName (if one exists); this would be in a StructuredName rnow
                for (ContentValues cv: emailValues) {
                    sendEmail(s, cv, emailCount++, displayName);
                }

                // Now, we'll send up groups, if any
                if (!groupIds.isEmpty()) {
                    boolean groupFirst = true;
                    for (int id: groupIds) {
                        // Since we get id's from the provider, we need to find their names
                        Cursor c = cr.query(ContentUris.withAppendedId(Groups.CONTENT_URI, id),
                                GROUP_TITLE_PROJECTION, null, null, null);
                        try {
                            // Presumably, this should always succeed, but ...
                            if (c.moveToFirst()) {
                                if (groupFirst) {
                                    s.start(Tags.CONTACTS_CATEGORIES);
                                    groupFirst = false;
                                }
                                s.data(Tags.CONTACTS_CATEGORY, c.getString(0));
                            }
                        } finally {
                            c.close();
                        }
                    }
                    if (!groupFirst) {
                        s.end();
                    }
                }
                s.end().end(); // ApplicationData & Change
                mUpdatedIdList.add(entityValues.getAsLong(RawContacts._ID));
            }
            if (!first) {
                s.end(); // Commands
            }
        } finally {
            ei.close();
        }

        return false;
    }
}
