1d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank/* 2d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * Copyright (C) 2008-2009 Marc Blank 3d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * Licensed to The Android Open Source Project. 4d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * 5d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * Licensed under the Apache License, Version 2.0 (the "License"); 6d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * you may not use this file except in compliance with the License. 7d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * You may obtain a copy of the License at 8d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * 9d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * http://www.apache.org/licenses/LICENSE-2.0 10d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * 11d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * Unless required by applicable law or agreed to in writing, software 12d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * distributed under the License is distributed on an "AS IS" BASIS, 13d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * See the License for the specific language governing permissions and 15d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * limitations under the License. 16d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank */ 17d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 18d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankpackage com.android.exchange.adapter; 19d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 20d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.content.ContentProviderClient; 21d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.content.ContentProviderOperation; 22d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.content.ContentProviderOperation.Builder; 23d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.content.ContentProviderResult; 24d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.content.ContentResolver; 25d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.content.ContentUris; 26d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.content.ContentValues; 27d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.content.Entity; 28d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.content.Entity.NamedContentValues; 29d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.content.EntityIterator; 30d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.content.OperationApplicationException; 31d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.database.Cursor; 32d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.net.Uri; 33d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.os.RemoteException; 34d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract; 35d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.CommonDataKinds.Email; 36d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.CommonDataKinds.Event; 37d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 38d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.CommonDataKinds.Im; 39d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.CommonDataKinds.Nickname; 40d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.CommonDataKinds.Note; 41d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.CommonDataKinds.Organization; 42d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.CommonDataKinds.Phone; 43d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.CommonDataKinds.Photo; 44d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.CommonDataKinds.Relation; 45d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 46d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 47d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.CommonDataKinds.Website; 48d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.Data; 49d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.Groups; 50d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.RawContacts; 51d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.RawContactsEntity; 52d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.Settings; 53d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.ContactsContract.SyncState; 54d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.provider.SyncStateContract; 55d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.text.TextUtils; 56d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.text.util.Rfc822Token; 57d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.text.util.Rfc822Tokenizer; 58d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.util.Base64; 59d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport android.util.Log; 60d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 610969df734735b0b55cc6a800335f665b40c8ecd6Marc Blankimport com.android.emailcommon.utility.Utility; 62d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport com.android.exchange.CommandStatusException; 63d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport com.android.exchange.Eas; 64d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport com.android.exchange.EasSyncService; 650969df734735b0b55cc6a800335f665b40c8ecd6Marc Blankimport com.android.exchange.utility.CalendarUtilities; 66d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 67d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport java.io.IOException; 68d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport java.io.InputStream; 69d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankimport java.util.ArrayList; 700969df734735b0b55cc6a800335f665b40c8ecd6Marc Blankimport java.util.GregorianCalendar; 710969df734735b0b55cc6a800335f665b40c8ecd6Marc Blankimport java.util.TimeZone; 72d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 73d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank/** 74d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * Sync adapter for EAS Contacts 75d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * 76d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank */ 77d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blankpublic class ContactsSyncAdapter extends AbstractSyncAdapter { 78d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 79d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final String TAG = "EasContactsSyncAdapter"; 80d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final String SERVER_ID_SELECTION = RawContacts.SOURCE_ID + "=?"; 81d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final String CLIENT_ID_SELECTION = RawContacts.SYNC1 + "=?"; 82d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final String[] ID_PROJECTION = new String[] {RawContacts._ID}; 83d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final String[] GROUP_TITLE_PROJECTION = new String[] {Groups.TITLE}; 84d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final String MIMETYPE_GROUP_MEMBERSHIP_AND_ID_EQUALS = Data.MIMETYPE + "='" + 85d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank GroupMembership.CONTENT_ITEM_TYPE + "' AND " + GroupMembership.GROUP_ROW_ID + "=?"; 86d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final String[] GROUPS_ID_PROJECTION = new String[] {Groups._ID}; 87d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 88d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final ArrayList<NamedContentValues> EMPTY_ARRAY_NAMEDCONTENTVALUES 89d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank = new ArrayList<NamedContentValues>(); 90d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 91d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final String FOUND_DATA_ROW = "com.android.exchange.FOUND_ROW"; 92d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 93d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final int[] HOME_ADDRESS_TAGS = new int[] {Tags.CONTACTS_HOME_ADDRESS_CITY, 94d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_HOME_ADDRESS_COUNTRY, 95d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_HOME_ADDRESS_POSTAL_CODE, 96d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_HOME_ADDRESS_STATE, 97d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_HOME_ADDRESS_STREET}; 98d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 99d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final int[] WORK_ADDRESS_TAGS = new int[] {Tags.CONTACTS_BUSINESS_ADDRESS_CITY, 100d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_BUSINESS_ADDRESS_COUNTRY, 101d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_BUSINESS_ADDRESS_POSTAL_CODE, 102d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_BUSINESS_ADDRESS_STATE, 103d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_BUSINESS_ADDRESS_STREET}; 104d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 105d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final int[] OTHER_ADDRESS_TAGS = new int[] {Tags.CONTACTS_HOME_ADDRESS_CITY, 106d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_OTHER_ADDRESS_COUNTRY, 107d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_OTHER_ADDRESS_POSTAL_CODE, 108d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_OTHER_ADDRESS_STATE, 109d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_OTHER_ADDRESS_STREET}; 110d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 111d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final int MAX_IM_ROWS = 3; 112d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final int MAX_EMAIL_ROWS = 3; 113d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final int MAX_PHONE_ROWS = 2; 114d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final String COMMON_DATA_ROW = Im.DATA; // Could have been Email.DATA, etc. 115d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final String COMMON_TYPE_ROW = Phone.TYPE; // Could have been any typed row 116d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 117d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final int[] IM_TAGS = new int[] {Tags.CONTACTS2_IM_ADDRESS, 118d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS2_IM_ADDRESS_2, Tags.CONTACTS2_IM_ADDRESS_3}; 119d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 120d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final int[] EMAIL_TAGS = new int[] {Tags.CONTACTS_EMAIL1_ADDRESS, 121d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_EMAIL2_ADDRESS, Tags.CONTACTS_EMAIL3_ADDRESS}; 122d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 123d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final int[] WORK_PHONE_TAGS = new int[] {Tags.CONTACTS_BUSINESS_TELEPHONE_NUMBER, 124d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_BUSINESS2_TELEPHONE_NUMBER}; 125d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 126d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final int[] HOME_PHONE_TAGS = new int[] {Tags.CONTACTS_HOME_TELEPHONE_NUMBER, 127d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Tags.CONTACTS_HOME2_TELEPHONE_NUMBER}; 128d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 129d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final Object sSyncKeyLock = new Object(); 130d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 131d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ArrayList<Long> mDeletedIdList = new ArrayList<Long>(); 132d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ArrayList<Long> mUpdatedIdList = new ArrayList<Long>(); 133d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 134d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private final Uri mAccountUri; 135d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private final ContentResolver mContentResolver; 136d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private boolean mGroupsUsed = false; 137d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 138d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public ContactsSyncAdapter(EasSyncService service) { 139d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank super(service); 140d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mAccountUri = uriWithAccountAndIsSyncAdapter(RawContacts.CONTENT_URI); 141d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mContentResolver = mContext.getContentResolver(); 142d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 143d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 144d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank static Uri addCallerIsSyncAdapterParameter(Uri uri) { 145d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return uri.buildUpon() 146d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true") 147d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .build(); 148d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 149d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 150d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank @Override 1510969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank public void sendSyncOptions(Double protocolVersion, Serializer s, boolean initialSync) 1520969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank throws IOException { 1530969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank if (initialSync) { 1540969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank // These are the tags we support for upload; whenever we add/remove support 1550969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank // (in addData), we need to update this list 1560969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.start(Tags.SYNC_SUPPORTED); 1570969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_FIRST_NAME); 1580969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_LAST_NAME); 1590969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_MIDDLE_NAME); 1600969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_SUFFIX); 1610969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_COMPANY_NAME); 1620969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_JOB_TITLE); 1630969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_EMAIL1_ADDRESS); 1640969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_EMAIL2_ADDRESS); 1650969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_EMAIL3_ADDRESS); 1660969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_BUSINESS2_TELEPHONE_NUMBER); 1670969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_BUSINESS_TELEPHONE_NUMBER); 1680969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS2_MMS); 1690969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_BUSINESS_FAX_NUMBER); 1700969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS2_COMPANY_MAIN_PHONE); 1710969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_HOME_FAX_NUMBER); 1720969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_HOME_TELEPHONE_NUMBER); 1730969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_HOME2_TELEPHONE_NUMBER); 1740969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_MOBILE_TELEPHONE_NUMBER); 1750969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_CAR_TELEPHONE_NUMBER); 1760969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_RADIO_TELEPHONE_NUMBER); 1770969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_PAGER_NUMBER); 1780969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_ASSISTANT_TELEPHONE_NUMBER); 1790969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS2_IM_ADDRESS); 1800969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS2_IM_ADDRESS_2); 1810969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS2_IM_ADDRESS_3); 1820969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_BUSINESS_ADDRESS_CITY); 1830969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_BUSINESS_ADDRESS_COUNTRY); 1840969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_BUSINESS_ADDRESS_POSTAL_CODE); 1850969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_BUSINESS_ADDRESS_STATE); 1860969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_BUSINESS_ADDRESS_STREET); 1870969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_HOME_ADDRESS_CITY); 1880969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_HOME_ADDRESS_COUNTRY); 1890969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_HOME_ADDRESS_POSTAL_CODE); 1900969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_HOME_ADDRESS_STATE); 1910969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_HOME_ADDRESS_STREET); 1920969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_OTHER_ADDRESS_CITY); 1930969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_OTHER_ADDRESS_COUNTRY); 1940969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_OTHER_ADDRESS_POSTAL_CODE); 1950969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_OTHER_ADDRESS_STATE); 1960969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_OTHER_ADDRESS_STREET); 1970969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_YOMI_COMPANY_NAME); 1980969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_YOMI_FIRST_NAME); 1990969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_YOMI_LAST_NAME); 2000969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS2_NICKNAME); 2010969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_ASSISTANT_NAME); 2020969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS2_MANAGER_NAME); 2030969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_SPOUSE); 2040969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_DEPARTMENT); 2050969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_TITLE); 2060969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_OFFICE_LOCATION); 2070969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS2_CUSTOMER_ID); 2080969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS2_GOVERNMENT_ID); 2090969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS2_ACCOUNT_NAME); 2100969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_ANNIVERSARY); 2110969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_BIRTHDAY); 2120969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_WEBPAGE); 2130969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.tag(Tags.CONTACTS_PICTURE); 2140969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank s.end(); // SYNC_SUPPORTED 2150969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank } else { 2160969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank setPimSyncOptions(protocolVersion, null, s); 2170969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank } 218d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 219d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 220d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank @Override 221d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public boolean isSyncable() { 222d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return ContentResolver.getSyncAutomatically( 223d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mAccountManagerAccount, ContactsContract.AUTHORITY); 224d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 225d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 226d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank @Override 227d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public boolean parse(InputStream is) throws IOException, CommandStatusException { 228d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank EasContactsSyncParser p = new EasContactsSyncParser(is, this); 229d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return p.parse(); 230d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 231d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 232d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 233d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank @Override 234d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void wipe() { 235d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mContentResolver.delete(mAccountUri, null, null); 236d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 237d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 238d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank interface UntypedRow { 239d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addValues(RowBuilder builder); 240d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public boolean isSameAs(int type, String value); 241d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 242d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 243d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank /** 244d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * We get our SyncKey from ContactsProvider. If there's not one, we set it to "0" (the reset 245d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * state) and save that away. 246d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank */ 247d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank @Override 248d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public String getSyncKey() throws IOException { 249d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank synchronized (sSyncKeyLock) { 250d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentProviderClient client = mService.mContentResolver 251d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .acquireContentProviderClient(ContactsContract.AUTHORITY_URI); 252d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank try { 253d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank byte[] data = SyncStateContract.Helpers.get(client, 254d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContactsContract.SyncState.CONTENT_URI, mAccountManagerAccount); 255d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (data == null || data.length == 0) { 256d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Initialize the SyncKey 257d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank setSyncKey("0", false); 258d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Make sure ungrouped contacts for Exchange are defaultly visible 259d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = new ContentValues(); 260d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cv.put(Groups.ACCOUNT_NAME, mAccount.mEmailAddress); 261d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cv.put(Groups.ACCOUNT_TYPE, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE); 262d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cv.put(Settings.UNGROUPED_VISIBLE, true); 263d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank client.insert(addCallerIsSyncAdapterParameter(Settings.CONTENT_URI), cv); 264d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return "0"; 265d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else { 266d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return new String(data); 267d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 268d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } catch (RemoteException e) { 269d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank throw new IOException("Can't get SyncKey from ContactsProvider"); 270d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 271d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 272d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 273d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 274d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank /** 275d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * We only need to set this when we're forced to make the SyncKey "0" (a reset). In all other 276d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * cases, the SyncKey is set within ContactOperations 277d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank */ 278d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank @Override 279d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void setSyncKey(String syncKey, boolean inCommands) throws IOException { 280d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank synchronized (sSyncKeyLock) { 281d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if ("0".equals(syncKey) || !inCommands) { 282d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentProviderClient client = mService.mContentResolver 283d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .acquireContentProviderClient(ContactsContract.AUTHORITY_URI); 284d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank try { 285d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank SyncStateContract.Helpers.set(client, ContactsContract.SyncState.CONTENT_URI, 286d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mAccountManagerAccount, syncKey.getBytes()); 287d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank userLog("SyncKey set to ", syncKey, " in ContactsProvider"); 288d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } catch (RemoteException e) { 289d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank throw new IOException("Can't set SyncKey in ContactsProvider"); 290d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 291d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 292d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mMailbox.mSyncKey = syncKey; 293d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 294d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 295d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 296d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public static final class EasChildren { 297d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private EasChildren() {} 298d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 299d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank /** MIME type used when storing this in data table. */ 300d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/eas_children"; 301d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public static final int MAX_CHILDREN = 8; 302d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public static final String[] ROWS = 303d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank new String[] {"data2", "data3", "data4", "data5", "data6", "data7", "data8", "data9"}; 304d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 305d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 306d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public static final class EasPersonal { 307d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String anniversary; 308d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String fileAs; 309d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 310d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank /** MIME type used when storing this in data table. */ 311d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/eas_personal"; 312d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public static final String ANNIVERSARY = "data2"; 313d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public static final String FILE_AS = "data4"; 314d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 315d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank boolean hasData() { 316d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return anniversary != null || fileAs != null; 317d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 318d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 319d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 320d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public static final class EasBusiness { 321d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String customerId; 322d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String governmentId; 323d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String accountName; 324d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 325d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank /** MIME type used when storing this in data table. */ 326d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/eas_business"; 327d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public static final String CUSTOMER_ID = "data6"; 328d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public static final String GOVERNMENT_ID = "data7"; 329d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public static final String ACCOUNT_NAME = "data8"; 330d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 331d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank boolean hasData() { 332d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return customerId != null || governmentId != null || accountName != null; 333d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 334d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 335d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 336d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public static final class Address { 337d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String city; 338d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String country; 339d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String code; 340d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String street; 341d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String state; 342d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 343d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank boolean hasData() { 344d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return city != null || country != null || code != null || state != null 345d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank || street != null; 346d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 347d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 348d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 349d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank class EmailRow implements UntypedRow { 350d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String email; 351d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String displayName; 352d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 353d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public EmailRow(String _email) { 354d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(_email); 355d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Can't happen, but belt & suspenders 356d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (tokens.length == 0) { 357d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank email = ""; 358d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank displayName = ""; 359d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else { 360d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Rfc822Token token = tokens[0]; 361d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank email = token.getAddress(); 362d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank displayName = token.getName(); 363d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 364d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 365d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 3660969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank @Override 367d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addValues(RowBuilder builder) { 368d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Email.DATA, email); 369d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Email.DISPLAY_NAME, displayName); 370d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 371d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 3720969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank @Override 373d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public boolean isSameAs(int type, String value) { 374d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return email.equalsIgnoreCase(value); 375d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 376d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 377d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 378d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank class ImRow implements UntypedRow { 379d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String im; 380d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 381d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public ImRow(String _im) { 382d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank im = _im; 383d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 384d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 3850969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank @Override 386d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addValues(RowBuilder builder) { 387d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Im.DATA, im); 388d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 389d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 3900969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank @Override 391d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public boolean isSameAs(int type, String value) { 392d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return im.equalsIgnoreCase(value); 393d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 394d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 395d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 396d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank class PhoneRow implements UntypedRow { 397d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String phone; 398d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int type; 399d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 400d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public PhoneRow(String _phone, int _type) { 401d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank phone = _phone; 402d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank type = _type; 403d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 404d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 4050969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank @Override 406d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addValues(RowBuilder builder) { 407d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Im.DATA, phone); 408d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Phone.TYPE, type); 409d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 410d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 4110969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank @Override 412d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public boolean isSameAs(int _type, String value) { 413d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return type == _type && phone.equalsIgnoreCase(value); 414d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 415d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 416d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 417d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank class EasContactsSyncParser extends AbstractSyncParser { 418d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 419d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String[] mBindArgument = new String[1]; 420d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String mMailboxIdAsString; 421d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContactOperations ops = new ContactOperations(); 422d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 423d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public EasContactsSyncParser(InputStream in, ContactsSyncAdapter adapter) 424d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank throws IOException { 425d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank super(in, adapter); 426d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 427d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 428d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addData(String serverId, ContactOperations ops, Entity entity) 429d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank throws IOException { 430d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String prefix = null; 431d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String firstName = null; 432d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String lastName = null; 433d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String middleName = null; 434d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String suffix = null; 435d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String companyName = null; 436d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String yomiFirstName = null; 437d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String yomiLastName = null; 438d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String yomiCompanyName = null; 439d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String title = null; 440d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String department = null; 441d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String officeLocation = null; 442d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Address home = new Address(); 443d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Address work = new Address(); 444d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Address other = new Address(); 445d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank EasBusiness business = new EasBusiness(); 446d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank EasPersonal personal = new EasPersonal(); 447d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ArrayList<String> children = new ArrayList<String>(); 448d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ArrayList<UntypedRow> emails = new ArrayList<UntypedRow>(); 449d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ArrayList<UntypedRow> ims = new ArrayList<UntypedRow>(); 450d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ArrayList<UntypedRow> homePhones = new ArrayList<UntypedRow>(); 451d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ArrayList<UntypedRow> workPhones = new ArrayList<UntypedRow>(); 452d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (entity == null) { 453d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.newContact(serverId); 454d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 455d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 456d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank while (nextTag(Tags.SYNC_APPLICATION_DATA) != END) { 457d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank switch (tag) { 458d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_FIRST_NAME: 459d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank firstName = getValue(); 460d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 461d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_LAST_NAME: 462d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank lastName = getValue(); 463d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 464d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_MIDDLE_NAME: 465d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank middleName = getValue(); 466d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 467d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_SUFFIX: 468d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank suffix = getValue(); 469d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 470d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_COMPANY_NAME: 471d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank companyName = getValue(); 472d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 473d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_JOB_TITLE: 474d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank title = getValue(); 475d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 476d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_EMAIL1_ADDRESS: 477d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_EMAIL2_ADDRESS: 478d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_EMAIL3_ADDRESS: 479d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank emails.add(new EmailRow(getValue())); 480d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 481d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_BUSINESS2_TELEPHONE_NUMBER: 482d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_BUSINESS_TELEPHONE_NUMBER: 483d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank workPhones.add(new PhoneRow(getValue(), Phone.TYPE_WORK)); 484d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 485d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS2_MMS: 486d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addPhone(entity, Phone.TYPE_MMS, getValue()); 487d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 488d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_BUSINESS_FAX_NUMBER: 489d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addPhone(entity, Phone.TYPE_FAX_WORK, getValue()); 490d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 491d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS2_COMPANY_MAIN_PHONE: 492d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addPhone(entity, Phone.TYPE_COMPANY_MAIN, getValue()); 493d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 494d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_HOME_FAX_NUMBER: 495d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addPhone(entity, Phone.TYPE_FAX_HOME, getValue()); 496d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 497d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_HOME_TELEPHONE_NUMBER: 498d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_HOME2_TELEPHONE_NUMBER: 499d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank homePhones.add(new PhoneRow(getValue(), Phone.TYPE_HOME)); 500d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 501d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_MOBILE_TELEPHONE_NUMBER: 502d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addPhone(entity, Phone.TYPE_MOBILE, getValue()); 503d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 504d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_CAR_TELEPHONE_NUMBER: 505d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addPhone(entity, Phone.TYPE_CAR, getValue()); 506d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 507d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_RADIO_TELEPHONE_NUMBER: 508d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addPhone(entity, Phone.TYPE_RADIO, getValue()); 509d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 510d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_PAGER_NUMBER: 511d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addPhone(entity, Phone.TYPE_PAGER, getValue()); 512d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 513d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_ASSISTANT_TELEPHONE_NUMBER: 514d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addPhone(entity, Phone.TYPE_ASSISTANT, getValue()); 515d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 516d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS2_IM_ADDRESS: 517d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS2_IM_ADDRESS_2: 518d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS2_IM_ADDRESS_3: 519d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ims.add(new ImRow(getValue())); 520d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 521d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_BUSINESS_ADDRESS_CITY: 522d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank work.city = getValue(); 523d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 524d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_BUSINESS_ADDRESS_COUNTRY: 525d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank work.country = getValue(); 526d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 527d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_BUSINESS_ADDRESS_POSTAL_CODE: 528d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank work.code = getValue(); 529d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 530d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_BUSINESS_ADDRESS_STATE: 531d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank work.state = getValue(); 532d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 533d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_BUSINESS_ADDRESS_STREET: 534d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank work.street = getValue(); 535d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 536d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_HOME_ADDRESS_CITY: 537d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank home.city = getValue(); 538d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 539d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_HOME_ADDRESS_COUNTRY: 540d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank home.country = getValue(); 541d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 542d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_HOME_ADDRESS_POSTAL_CODE: 543d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank home.code = getValue(); 544d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 545d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_HOME_ADDRESS_STATE: 546d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank home.state = getValue(); 547d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 548d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_HOME_ADDRESS_STREET: 549d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank home.street = getValue(); 550d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 551d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_OTHER_ADDRESS_CITY: 552d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank other.city = getValue(); 553d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 554d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_OTHER_ADDRESS_COUNTRY: 555d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank other.country = getValue(); 556d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 557d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_OTHER_ADDRESS_POSTAL_CODE: 558d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank other.code = getValue(); 559d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 560d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_OTHER_ADDRESS_STATE: 561d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank other.state = getValue(); 562d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 563d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_OTHER_ADDRESS_STREET: 564d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank other.street = getValue(); 565d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 566d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 567d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_CHILDREN: 568d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank childrenParser(children); 569d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 570d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 571d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_YOMI_COMPANY_NAME: 572d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank yomiCompanyName = getValue(); 573d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 574d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_YOMI_FIRST_NAME: 575d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank yomiFirstName = getValue(); 576d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 577d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_YOMI_LAST_NAME: 578d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank yomiLastName = getValue(); 579d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 580d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 581d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS2_NICKNAME: 582d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addNickname(entity, getValue()); 583d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 584d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 585d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_ASSISTANT_NAME: 586d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addRelation(entity, Relation.TYPE_ASSISTANT, getValue()); 587d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 588d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS2_MANAGER_NAME: 589d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addRelation(entity, Relation.TYPE_MANAGER, getValue()); 590d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 591d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_SPOUSE: 592d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addRelation(entity, Relation.TYPE_SPOUSE, getValue()); 593d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 594d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_DEPARTMENT: 595d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank department = getValue(); 596d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 597d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_TITLE: 598d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank prefix = getValue(); 599d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 600d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 601d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // EAS Business 602d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_OFFICE_LOCATION: 603d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank officeLocation = getValue(); 604d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 605d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS2_CUSTOMER_ID: 606d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank business.customerId = getValue(); 607d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 608d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS2_GOVERNMENT_ID: 609d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank business.governmentId = getValue(); 610d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 611d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS2_ACCOUNT_NAME: 612d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank business.accountName = getValue(); 613d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 614d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 615d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // EAS Personal 616d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_ANNIVERSARY: 617d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank personal.anniversary = getValue(); 618d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 619d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_BIRTHDAY: 620d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addBirthday(entity, getValue()); 621d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 622d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_WEBPAGE: 623d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addWebpage(entity, getValue()); 624d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 625d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 626d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_PICTURE: 627d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addPhoto(entity, getValue()); 628d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 629d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 630d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.BASE_BODY: 631d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addNote(entity, bodyParser()); 632d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 633d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_BODY: 634d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addNote(entity, getValue()); 635d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 636d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 637d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_CATEGORIES: 638d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mGroupsUsed = true; 639d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank categoriesParser(ops, entity); 640d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 641d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 642d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank default: 643d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank skipTag(); 644d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 645d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 646d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 647d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // We must have first name, last name, or company name 648d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String name = null; 649d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (firstName != null || lastName != null) { 650d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (firstName == null) { 651d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank name = lastName; 652d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (lastName == null) { 653d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank name = firstName; 654d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else { 655d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank name = firstName + ' ' + lastName; 656d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 657d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (companyName != null) { 658d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank name = companyName; 659d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 660d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 661d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addName(entity, prefix, firstName, lastName, middleName, suffix, name, 6620969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank yomiFirstName, yomiLastName); 663d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addBusiness(entity, business); 664d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addPersonal(entity, personal); 665d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 666d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addUntyped(entity, emails, Email.CONTENT_ITEM_TYPE, -1, MAX_EMAIL_ROWS); 667d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addUntyped(entity, ims, Im.CONTENT_ITEM_TYPE, -1, MAX_IM_ROWS); 668d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addUntyped(entity, homePhones, Phone.CONTENT_ITEM_TYPE, Phone.TYPE_HOME, 669d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank MAX_PHONE_ROWS); 670d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addUntyped(entity, workPhones, Phone.CONTENT_ITEM_TYPE, Phone.TYPE_WORK, 671d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank MAX_PHONE_ROWS); 672d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 673d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (!children.isEmpty()) { 674d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addChildren(entity, children); 675d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 676d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 677d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (work.hasData()) { 678d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addPostal(entity, StructuredPostal.TYPE_WORK, work.street, work.city, 679d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank work.state, work.country, work.code); 680d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 681d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (home.hasData()) { 682d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addPostal(entity, StructuredPostal.TYPE_HOME, home.street, home.city, 683d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank home.state, home.country, home.code); 684d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 685d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (other.hasData()) { 686d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addPostal(entity, StructuredPostal.TYPE_OTHER, other.street, other.city, 687d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank other.state, other.country, other.code); 688d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 689d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 690d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (companyName != null) { 691d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addOrganization(entity, Organization.TYPE_WORK, companyName, title, department, 692d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank yomiCompanyName, officeLocation); 693d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 694d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 695d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (entity != null) { 696d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // We've been removing rows from the list as they've been found in the xml 697d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Any that are left must have been deleted on the server 698d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ArrayList<NamedContentValues> ncvList = entity.getSubValues(); 699d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (NamedContentValues ncv: ncvList) { 700d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // These rows need to be deleted... 701d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Uri u = dataUriFromNamedContentValues(ncv); 702d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.add(ContentProviderOperation.newDelete(addCallerIsSyncAdapterParameter(u)) 703d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .build()); 704d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 705d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 706d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 707d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 708d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void categoriesParser(ContactOperations ops, Entity entity) throws IOException { 709d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank while (nextTag(Tags.CONTACTS_CATEGORIES) != END) { 710d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank switch (tag) { 711d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_CATEGORY: 712d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.addGroup(entity, getValue()); 713d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 714d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank default: 715d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank skipTag(); 716d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 717d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 718d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 719d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 720d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void childrenParser(ArrayList<String> children) throws IOException { 721d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank while (nextTag(Tags.CONTACTS_CHILDREN) != END) { 722d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank switch (tag) { 723d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.CONTACTS_CHILD: 724d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (children.size() < EasChildren.MAX_CHILDREN) { 725d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank children.add(getValue()); 726d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 727d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 728d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank default: 729d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank skipTag(); 730d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 731d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 732d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 733d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 734d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private String bodyParser() throws IOException { 735d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String body = null; 736d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank while (nextTag(Tags.BASE_BODY) != END) { 737d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank switch (tag) { 738d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.BASE_DATA: 739d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank body = getValue(); 740d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 741d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank default: 742d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank skipTag(); 743d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 744d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 745d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return body; 746d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 747d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 748d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addParser(ContactOperations ops) throws IOException { 749d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String serverId = null; 750d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank while (nextTag(Tags.SYNC_ADD) != END) { 751d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank switch (tag) { 752d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.SYNC_SERVER_ID: // same as 753d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank serverId = getValue(); 754d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 755d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.SYNC_APPLICATION_DATA: 756d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank addData(serverId, ops, null); 757d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 758d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank default: 759d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank skipTag(); 760d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 761d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 762d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 763d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 764d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private Cursor getServerIdCursor(String serverId) { 765d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mBindArgument[0] = serverId; 766d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return mContentResolver.query(mAccountUri, ID_PROJECTION, SERVER_ID_SELECTION, 767d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mBindArgument, null); 768d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 769d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 770d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private Cursor getClientIdCursor(String clientId) { 771d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mBindArgument[0] = clientId; 772d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return mContentResolver.query(mAccountUri, ID_PROJECTION, CLIENT_ID_SELECTION, 773d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mBindArgument, null); 774d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 775d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 776d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void deleteParser(ContactOperations ops) throws IOException { 777d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank while (nextTag(Tags.SYNC_DELETE) != END) { 778d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank switch (tag) { 779d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.SYNC_SERVER_ID: 780d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String serverId = getValue(); 781d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Find the message in this mailbox with the given serverId 782d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Cursor c = getServerIdCursor(serverId); 783d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank try { 784d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (c.moveToFirst()) { 785d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank userLog("Deleting ", serverId); 786d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.delete(c.getLong(0)); 787d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 788d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } finally { 789d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank c.close(); 790d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 791d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 792d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank default: 793d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank skipTag(); 794d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 795d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 796d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 797d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 798d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank class ServerChange { 799d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank long id; 800d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank boolean read; 801d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 802d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ServerChange(long _id, boolean _read) { 803d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank id = _id; 804d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank read = _read; 805d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 806d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 807d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 808d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank /** 809d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * Changes are handled row by row, and only changed/new rows are acted upon 810d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param ops the array of pending ContactProviderOperations. 811d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @throws IOException 812d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank */ 813d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void changeParser(ContactOperations ops) throws IOException { 814d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String serverId = null; 815d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Entity entity = null; 816d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank while (nextTag(Tags.SYNC_CHANGE) != END) { 817d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank switch (tag) { 818d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.SYNC_SERVER_ID: 819d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank serverId = getValue(); 820d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Cursor c = getServerIdCursor(serverId); 821d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank try { 822d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (c.moveToFirst()) { 823d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // TODO Handle deleted individual rows... 824d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Uri uri = ContentUris.withAppendedId( 825d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RawContacts.CONTENT_URI, c.getLong(0)); 826d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank uri = Uri.withAppendedPath( 827d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank uri, RawContacts.Entity.CONTENT_DIRECTORY); 828d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank EntityIterator entityIterator = RawContacts.newEntityIterator( 829d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mContentResolver.query(uri, null, null, null, null)); 830d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (entityIterator.hasNext()) { 831d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank entity = entityIterator.next(); 832d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 833d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank userLog("Changing contact ", serverId); 834d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 835d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } finally { 836d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank c.close(); 837d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 838d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 839d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.SYNC_APPLICATION_DATA: 840d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank addData(serverId, ops, entity); 841d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 842d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank default: 843d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank skipTag(); 844d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 845d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 846d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 847d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 848d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank @Override 849d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void commandsParser() throws IOException { 850d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank while (nextTag(Tags.SYNC_COMMANDS) != END) { 851d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (tag == Tags.SYNC_ADD) { 852d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank addParser(ops); 853d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank incrementChangeCount(); 854d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (tag == Tags.SYNC_DELETE) { 855d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank deleteParser(ops); 856d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank incrementChangeCount(); 857d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (tag == Tags.SYNC_CHANGE) { 858d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank changeParser(ops); 859d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank incrementChangeCount(); 860d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else 861d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank skipTag(); 862d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 863d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 864d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 865d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank @Override 866d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void commit() throws IOException { 867d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Save the syncKey here, using the Helper provider by Contacts provider 868d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank userLog("Contacts SyncKey saved as: ", mMailbox.mSyncKey); 869d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.add(SyncStateContract.Helpers.newSetOperation(SyncState.CONTENT_URI, 870d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mAccountManagerAccount, mMailbox.mSyncKey.getBytes())); 871d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 872d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Execute these all at once... 873d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.execute(); 874d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 875d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (ops.mResults != null) { 876d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = new ContentValues(); 877d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cv.put(RawContacts.DIRTY, 0); 878d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (int i = 0; i < ops.mContactIndexCount; i++) { 879d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int index = ops.mContactIndexArray[i]; 880d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Uri u = ops.mResults[index].uri; 881d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (u != null) { 882d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String idString = u.getLastPathSegment(); 883d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mContentResolver.update( 884d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank addCallerIsSyncAdapterParameter(RawContacts.CONTENT_URI), cv, 885d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RawContacts._ID + "=" + idString, null); 886d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 887d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 888d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 889d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 890d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 891d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addResponsesParser() throws IOException { 892d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String serverId = null; 893d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String clientId = null; 894d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = new ContentValues(); 895d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank while (nextTag(Tags.SYNC_ADD) != END) { 896d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank switch (tag) { 897d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.SYNC_SERVER_ID: 898d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank serverId = getValue(); 899d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 900d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.SYNC_CLIENT_ID: 901d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank clientId = getValue(); 902d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 903d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.SYNC_STATUS: 904d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank getValue(); 905d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 906d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank default: 907d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank skipTag(); 908d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 909d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 910d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 911d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // This is theoretically impossible, but... 912d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (clientId == null || serverId == null) return; 913d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 914d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Cursor c = getClientIdCursor(clientId); 915d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank try { 916d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (c.moveToFirst()) { 917d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cv.put(RawContacts.SOURCE_ID, serverId); 918d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cv.put(RawContacts.DIRTY, 0); 919d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.add(ContentProviderOperation.newUpdate( 920d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentUris.withAppendedId( 921d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank addCallerIsSyncAdapterParameter(RawContacts.CONTENT_URI), 922d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank c.getLong(0))) 923d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .withValues(cv) 924d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .build()); 925d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank userLog("New contact " + clientId + " was given serverId: " + serverId); 926d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 927d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } finally { 928d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank c.close(); 929d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 930d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 931d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 932d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void changeResponsesParser() throws IOException { 933d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String serverId = null; 934d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String status = null; 935d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank while (nextTag(Tags.SYNC_CHANGE) != END) { 936d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank switch (tag) { 937d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.SYNC_SERVER_ID: 938d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank serverId = getValue(); 939d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 940d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Tags.SYNC_STATUS: 941d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank status = getValue(); 942d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 943d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank default: 944d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank skipTag(); 945d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 946d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 947d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (serverId != null && status != null) { 948d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank userLog("Changed contact " + serverId + " failed with status: " + status); 949d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 950d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 951d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 952d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 953d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank @Override 954d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void responsesParser() throws IOException { 955d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Handle server responses here (for Add and Change) 956d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank while (nextTag(Tags.SYNC_RESPONSES) != END) { 957d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (tag == Tags.SYNC_ADD) { 958d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank addResponsesParser(); 959d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (tag == Tags.SYNC_CHANGE) { 960d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank changeResponsesParser(); 961d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else 962d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank skipTag(); 963d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 964d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 965d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 966d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 967d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 968d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private Uri uriWithAccountAndIsSyncAdapter(Uri uri) { 969d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return uri.buildUpon() 970d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .appendQueryParameter(RawContacts.ACCOUNT_NAME, mAccount.mEmailAddress) 971d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .appendQueryParameter(RawContacts.ACCOUNT_TYPE, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE) 972d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true") 973d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .build(); 974d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 975d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 976d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank /** 977d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * SmartBuilder is a wrapper for the Builder class that is used to create/update rows for a 978d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * ContentProvider. It has, in addition to the Builder, ContentValues which, if present, 979d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * represent the current values of that row, that can be compared against current values to 980d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * see whether an update is even necessary. The methods on SmartBuilder are delegated to 981d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * the Builder. 982d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank */ 983d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private class RowBuilder { 984d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Builder builder; 985d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv; 986d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 987d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public RowBuilder(Builder _builder) { 988d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder = _builder; 989d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 990d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 991d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public RowBuilder(Builder _builder, NamedContentValues _ncv) { 992d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder = _builder; 993d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cv = _ncv.values; 994d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 995d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 996b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook RowBuilder withValues(ContentValues values) { 997b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook builder.withValues(values); 998b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook return this; 999b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 1000b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 1001d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder withValueBackReference(String key, int previousResult) { 1002d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValueBackReference(key, previousResult); 1003d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return this; 1004d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1005d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1006d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentProviderOperation build() { 1007d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return builder.build(); 1008d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1009d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1010d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder withValue(String key, Object value) { 1011d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(key, value); 1012d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return this; 1013d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1014d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1015d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1016d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private class ContactOperations extends ArrayList<ContentProviderOperation> { 1017d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private static final long serialVersionUID = 1L; 1018d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private int mCount = 0; 1019d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private int mContactBackValue = mCount; 1020d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Make an array big enough for the PIM window (max items we can get) 1021d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private int[] mContactIndexArray = 1022d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank new int[Integer.parseInt(AbstractSyncAdapter.PIM_WINDOW_SIZE)]; 1023d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private int mContactIndexCount = 0; 1024d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private ContentProviderResult[] mResults = null; 1025d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1026d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank @Override 1027d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public boolean add(ContentProviderOperation op) { 1028d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank super.add(op); 1029d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mCount++; 1030d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return true; 1031d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1032d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1033d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void newContact(String serverId) { 1034d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Builder builder = ContentProviderOperation 1035d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .newInsert(uriWithAccountAndIsSyncAdapter(RawContacts.CONTENT_URI)); 1036d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues values = new ContentValues(); 1037d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank values.put(RawContacts.SOURCE_ID, serverId); 1038d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValues(values); 1039d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mContactBackValue = mCount; 1040d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mContactIndexArray[mContactIndexCount++] = mCount; 1041d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1042d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1043d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1044d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void delete(long id) { 1045d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(ContentProviderOperation 1046d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .newDelete(ContentUris.withAppendedId(RawContacts.CONTENT_URI, id) 1047d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .buildUpon() 1048d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true") 1049d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .build()) 1050d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .build()); 1051d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1052d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1053d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void execute() { 1054d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank synchronized (mService.getSynchronizer()) { 1055d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (!mService.isStopped()) { 1056d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank try { 1057d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (!isEmpty()) { 1058d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mService.userLog("Executing ", size(), " CPO's"); 1059d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mResults = mContext.getContentResolver().applyBatch( 1060d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContactsContract.AUTHORITY, this); 1061d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1062d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } catch (RemoteException e) { 1063d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // There is nothing sensible to be done here 1064d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Log.e(TAG, "problem inserting contact during server update", e); 1065d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } catch (OperationApplicationException e) { 1066d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // There is nothing sensible to be done here 1067d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Log.e(TAG, "problem inserting contact during server update", e); 1068d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1069d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1070d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1071d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1072d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1073d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank /** 1074d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * Given the list of NamedContentValues for an entity, a mime type, and a subtype, 1075d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * tries to find a match, returning it 1076d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param list the list of NCV's from the contact entity 1077d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param contentItemType the mime type we're looking for 1078d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param type the subtype (e.g. HOME, WORK, etc.) 1079d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @return the matching NCV or null if not found 1080d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank */ 1081d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private NamedContentValues findTypedData(ArrayList<NamedContentValues> list, 1082d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String contentItemType, int type, String stringType) { 1083d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank NamedContentValues result = null; 1084d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1085d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Loop through the ncv's, looking for an existing row 1086d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (NamedContentValues namedContentValues: list) { 1087d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Uri uri = namedContentValues.uri; 1088d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = namedContentValues.values; 1089d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (Data.CONTENT_URI.equals(uri)) { 1090d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String mimeType = cv.getAsString(Data.MIMETYPE); 1091d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (mimeType.equals(contentItemType)) { 1092d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (stringType != null) { 1093d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv.getAsString(GroupMembership.GROUP_ROW_ID).equals(stringType)) { 1094d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank result = namedContentValues; 1095d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1096d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Note Email.TYPE could be ANY type column; they are all defined in 1097d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // the private CommonColumns class in ContactsContract 1098d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // We'll accept either type < 0 (don't care), cv doesn't have a type, 1099d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // or the types are equal 1100d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (type < 0 || !cv.containsKey(Email.TYPE) || 1101d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cv.getAsInteger(Email.TYPE) == type) { 1102d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank result = namedContentValues; 1103d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1104d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1105d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1106d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1107d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1108d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // If we've found an existing data row, we'll delete it. Any rows left at the 1109d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // end should be deleted... 1110d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (result != null) { 1111d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank list.remove(result); 1112d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1113d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1114d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Return the row found (or null) 1115d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return result; 1116d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1117d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1118d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank /** 1119d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * Given the list of NamedContentValues for an entity and a mime type 1120d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * gather all of the matching NCV's, returning them 1121d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param list the list of NCV's from the contact entity 1122d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param contentItemType the mime type we're looking for 1123d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param type the subtype (e.g. HOME, WORK, etc.) 1124d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @return the matching NCVs 1125d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank */ 1126d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private ArrayList<NamedContentValues> findUntypedData(ArrayList<NamedContentValues> list, 1127d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int type, String contentItemType) { 1128d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ArrayList<NamedContentValues> result = new ArrayList<NamedContentValues>(); 1129d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1130d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Loop through the ncv's, looking for an existing row 1131d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (NamedContentValues namedContentValues: list) { 1132d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Uri uri = namedContentValues.uri; 1133d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = namedContentValues.values; 1134d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (Data.CONTENT_URI.equals(uri)) { 1135d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String mimeType = cv.getAsString(Data.MIMETYPE); 1136d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (mimeType.equals(contentItemType)) { 1137d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (type != -1) { 1138d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int subtype = cv.getAsInteger(Phone.TYPE); 1139d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (type != subtype) { 1140d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank continue; 1141d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1142d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1143d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank result.add(namedContentValues); 1144d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1145d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1146d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1147d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1148d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // If we've found an existing data row, we'll delete it. Any rows left at the 1149d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // end should be deleted... 1150d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (NamedContentValues values : result) { 1151d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank list.remove(values); 1152d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1153d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1154d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Return the row found (or null) 1155d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return result; 1156d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1157d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1158d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank /** 1159d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * Create a wrapper for a builder (insert or update) that also includes the NCV for 1160d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * an existing row of this type. If the SmartBuilder's cv field is not null, then 1161d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * it represents the current (old) values of this field. The caller can then check 1162d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * whether the field is now different and needs to be updated; if it's not different, 1163d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * the caller will simply return and not generate a new CPO. Otherwise, the builder 1164d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * should have its content values set, and the built CPO should be added to the 1165d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * ContactOperations list. 1166d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * 1167d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param entity the contact entity (or null if this is a new contact) 1168d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param mimeType the mime type of this row 1169d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param type the subtype of this row 1170d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param stringType for groups, the name of the group (type will be ignored), or null 1171d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @return the created SmartBuilder 1172d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank */ 1173d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public RowBuilder createBuilder(Entity entity, String mimeType, int type, 1174d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String stringType) { 1175d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = null; 1176d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1177d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (entity != null) { 1178d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank NamedContentValues ncv = 1179d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank findTypedData(entity.getSubValues(), mimeType, type, stringType); 1180d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (ncv != null) { 1181d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder = new RowBuilder( 1182d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentProviderOperation 1183d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .newUpdate(addCallerIsSyncAdapterParameter( 1184d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank dataUriFromNamedContentValues(ncv))), 1185d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ncv); 1186d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1187d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1188d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1189d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (builder == null) { 1190d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder = newRowBuilder(entity, mimeType); 1191d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1192d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1193d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Return the appropriate builder (insert or update) 1194d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Caller will fill in the appropriate values; 4 MIMETYPE is already set 1195d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return builder; 1196d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1197d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1198d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private RowBuilder typedRowBuilder(Entity entity, String mimeType, int type) { 1199d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return createBuilder(entity, mimeType, type, null); 1200d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1201d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1202d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private RowBuilder untypedRowBuilder(Entity entity, String mimeType) { 1203d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return createBuilder(entity, mimeType, -1, null); 1204d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1205d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1206d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private RowBuilder newRowBuilder(Entity entity, String mimeType) { 1207d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // This is a new row; first get the contactId 1208d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // If the Contact is new, use the saved back value; otherwise the value in the entity 1209d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int contactId = mContactBackValue; 1210d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (entity != null) { 1211d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank contactId = entity.getEntityValues().getAsInteger(RawContacts._ID); 1212d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1213d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1214d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Create an insert operation with the proper contactId reference 1215d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = 1216d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank new RowBuilder(ContentProviderOperation.newInsert( 1217d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank addCallerIsSyncAdapterParameter(Data.CONTENT_URI))); 1218d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (entity == null) { 1219d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValueBackReference(Data.RAW_CONTACT_ID, contactId); 1220d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else { 1221d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Data.RAW_CONTACT_ID, contactId); 1222d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1223d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1224d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Set the mime type of the row 1225d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Data.MIMETYPE, mimeType); 1226d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return builder; 1227d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1228d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1229d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank /** 1230d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * Compare a column in a ContentValues with an (old) value, and see if they are the 1231d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * same. For this purpose, null and an empty string are considered the same. 1232d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param cv a ContentValues object, from a NamedContentValues 1233d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param column a column that might be in the ContentValues 1234d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param oldValue an old value (or null) to check against 1235d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @return whether the column's value in the ContentValues matches oldValue 1236d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank */ 1237d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private boolean cvCompareString(ContentValues cv, String column, String oldValue) { 1238d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv.containsKey(column)) { 1239d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (oldValue != null && cv.getAsString(column).equals(oldValue)) { 1240d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return true; 1241d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1242d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (oldValue == null || oldValue.length() == 0) { 1243d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return true; 1244d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1245d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return false; 1246d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1247d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1248d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addChildren(Entity entity, ArrayList<String> children) { 1249d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = untypedRowBuilder(entity, EasChildren.CONTENT_ITEM_TYPE); 1250d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int i = 0; 1251d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (String child: children) { 1252d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(EasChildren.ROWS[i++], child); 1253d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1254d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1255d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1256d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1257d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addGroup(Entity entity, String group) { 1258d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = 1259d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank createBuilder(entity, GroupMembership.CONTENT_ITEM_TYPE, -1, group); 1260d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(GroupMembership.GROUP_SOURCE_ID, group); 1261d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1262d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1263d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1264d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addBirthday(Entity entity, String birthday) { 1265d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = 1266d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank typedRowBuilder(entity, Event.CONTENT_ITEM_TYPE, Event.TYPE_BIRTHDAY); 1267d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = builder.cv; 1268d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv != null && cvCompareString(cv, Event.START_DATE, birthday)) { 1269d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return; 1270d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 12710969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank long millis = Utility.parseEmailDateTimeToMillis(birthday); 12720969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); 12730969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank cal.setTimeInMillis(millis); 12740969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank if (cal.get(GregorianCalendar.HOUR_OF_DAY) >= 12) { 12750969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank cal.add(GregorianCalendar.DATE, 1); 12760969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank } 12770969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank String realBirthday = CalendarUtilities.calendarToBirthdayString(cal); 12780969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank builder.withValue(Event.START_DATE, realBirthday); 1279d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Event.TYPE, Event.TYPE_BIRTHDAY); 1280d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1281d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1282d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1283d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addName(Entity entity, String prefix, String givenName, String familyName, 1284d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String middleName, String suffix, String displayName, String yomiFirstName, 12850969df734735b0b55cc6a800335f665b40c8ecd6Marc Blank String yomiLastName) { 1286d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = untypedRowBuilder(entity, StructuredName.CONTENT_ITEM_TYPE); 1287d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = builder.cv; 1288d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv != null && cvCompareString(cv, StructuredName.GIVEN_NAME, givenName) && 1289d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, StructuredName.FAMILY_NAME, familyName) && 1290d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, StructuredName.MIDDLE_NAME, middleName) && 1291d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, StructuredName.PREFIX, prefix) && 1292d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, StructuredName.PHONETIC_GIVEN_NAME, yomiFirstName) && 1293d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, StructuredName.PHONETIC_FAMILY_NAME, yomiLastName) && 1294d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, StructuredName.SUFFIX, suffix)) { 1295d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return; 1296d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1297d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(StructuredName.GIVEN_NAME, givenName); 1298d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(StructuredName.FAMILY_NAME, familyName); 1299d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(StructuredName.MIDDLE_NAME, middleName); 1300d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(StructuredName.SUFFIX, suffix); 1301d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(StructuredName.PHONETIC_GIVEN_NAME, yomiFirstName); 1302d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(StructuredName.PHONETIC_FAMILY_NAME, yomiLastName); 1303d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(StructuredName.PREFIX, prefix); 1304d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1305d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1306d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1307d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addPersonal(Entity entity, EasPersonal personal) { 1308d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = untypedRowBuilder(entity, EasPersonal.CONTENT_ITEM_TYPE); 1309d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = builder.cv; 1310d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv != null && cvCompareString(cv, EasPersonal.ANNIVERSARY, personal.anniversary) && 1311d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, EasPersonal.FILE_AS , personal.fileAs)) { 1312d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return; 1313d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1314d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (!personal.hasData()) { 1315d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return; 1316d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1317d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(EasPersonal.FILE_AS, personal.fileAs); 1318d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(EasPersonal.ANNIVERSARY, personal.anniversary); 1319d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1320d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1321d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1322d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addBusiness(Entity entity, EasBusiness business) { 1323d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = untypedRowBuilder(entity, EasBusiness.CONTENT_ITEM_TYPE); 1324d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = builder.cv; 1325d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv != null && cvCompareString(cv, EasBusiness.ACCOUNT_NAME, business.accountName) && 1326d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, EasBusiness.CUSTOMER_ID, business.customerId) && 1327d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, EasBusiness.GOVERNMENT_ID, business.governmentId)) { 1328d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return; 1329d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1330d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (!business.hasData()) { 1331d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return; 1332d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1333d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(EasBusiness.ACCOUNT_NAME, business.accountName); 1334d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(EasBusiness.CUSTOMER_ID, business.customerId); 1335d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(EasBusiness.GOVERNMENT_ID, business.governmentId); 1336d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1337d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1338d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1339d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addPhoto(Entity entity, String photo) { 1340d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = untypedRowBuilder(entity, Photo.CONTENT_ITEM_TYPE); 1341d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // We're always going to add this; it's not worth trying to figure out whether the 1342d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // picture is the same as the one stored. 1343d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank byte[] pic = Base64.decode(photo, Base64.DEFAULT); 1344d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Photo.PHOTO, pic); 1345d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1346d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1347d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1348d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addPhone(Entity entity, int type, String phone) { 1349d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = typedRowBuilder(entity, Phone.CONTENT_ITEM_TYPE, type); 1350d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = builder.cv; 1351d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv != null && cvCompareString(cv, Phone.NUMBER, phone)) { 1352d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return; 1353d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1354d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Phone.TYPE, type); 1355d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Phone.NUMBER, phone); 1356d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1357d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1358d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1359d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addWebpage(Entity entity, String url) { 1360d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = untypedRowBuilder(entity, Website.CONTENT_ITEM_TYPE); 1361d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = builder.cv; 1362d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv != null && cvCompareString(cv, Website.URL, url)) { 1363d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return; 1364d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1365d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Website.TYPE, Website.TYPE_WORK); 1366d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Website.URL, url); 1367d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1368d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1369d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1370d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addRelation(Entity entity, int type, String value) { 1371d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = typedRowBuilder(entity, Relation.CONTENT_ITEM_TYPE, type); 1372d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = builder.cv; 1373d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv != null && cvCompareString(cv, Relation.DATA, value)) { 1374d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return; 1375d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1376d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Relation.TYPE, type); 1377d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Relation.DATA, value); 1378d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1379d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1380d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1381d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addNickname(Entity entity, String name) { 1382d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = 1383d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank typedRowBuilder(entity, Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE_DEFAULT); 1384d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = builder.cv; 1385d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv != null && cvCompareString(cv, Nickname.NAME, name)) { 1386d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return; 1387d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1388d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Nickname.TYPE, Nickname.TYPE_DEFAULT); 1389d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Nickname.NAME, name); 1390d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1391d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1392d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1393d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addPostal(Entity entity, int type, String street, String city, String state, 1394d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String country, String code) { 1395d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = typedRowBuilder(entity, StructuredPostal.CONTENT_ITEM_TYPE, 1396d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank type); 1397d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = builder.cv; 1398d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv != null && cvCompareString(cv, StructuredPostal.CITY, city) && 1399d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, StructuredPostal.STREET, street) && 1400d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, StructuredPostal.COUNTRY, country) && 1401d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, StructuredPostal.POSTCODE, code) && 1402d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, StructuredPostal.REGION, state)) { 1403d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return; 1404d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1405d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(StructuredPostal.TYPE, type); 1406d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(StructuredPostal.CITY, city); 1407d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(StructuredPostal.STREET, street); 1408d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(StructuredPostal.COUNTRY, country); 1409d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(StructuredPostal.POSTCODE, code); 1410d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(StructuredPostal.REGION, state); 1411d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1412d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1413d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1414d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank /** 1415d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * We now are dealing with up to maxRows typeless rows of mimeType data. We need to try to 1416d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * match them with existing rows; if there's a match, everything's great. Otherwise, we 1417d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * either need to add a new row for the data, or we have to replace an existing one 1418d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * that no longer matches. This is similar to the way Emails are handled. 1419d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank */ 1420d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addUntyped(Entity entity, ArrayList<UntypedRow> rows, String mimeType, 1421d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int type, int maxRows) { 1422d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Make a list of all same type rows in the existing entity 1423d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ArrayList<NamedContentValues> oldValues = EMPTY_ARRAY_NAMEDCONTENTVALUES; 1424d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ArrayList<NamedContentValues> entityValues = EMPTY_ARRAY_NAMEDCONTENTVALUES; 1425d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (entity != null) { 1426d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank oldValues = findUntypedData(entityValues, type, mimeType); 1427d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank entityValues = entity.getSubValues(); 1428d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1429d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1430d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // These will be rows needing replacement with new values 1431d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ArrayList<UntypedRow> rowsToReplace = new ArrayList<UntypedRow>(); 1432d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1433d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // The count of existing rows 1434d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int numRows = oldValues.size(); 1435d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (UntypedRow row: rows) { 1436d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank boolean found = false; 1437d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // If we already have this row, mark it 1438d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (NamedContentValues ncv: oldValues) { 1439d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = ncv.values; 1440d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String data = cv.getAsString(COMMON_DATA_ROW); 1441d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int rowType = -1; 1442d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv.containsKey(COMMON_TYPE_ROW)) { 1443d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank rowType = cv.getAsInteger(COMMON_TYPE_ROW); 1444d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1445d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (row.isSameAs(rowType, data)) { 1446d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cv.put(FOUND_DATA_ROW, true); 1447d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Remove this to indicate it's still being used 1448d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank entityValues.remove(ncv); 1449d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank found = true; 1450d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1451d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1452d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1453d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (!found) { 1454d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // If we don't, there are two possibilities 1455d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (numRows < maxRows) { 1456d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // If there are available rows, add a new one 1457d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = newRowBuilder(entity, mimeType); 1458d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank row.addValues(builder); 1459d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1460d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank numRows++; 1461d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else { 1462d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Otherwise, say we need to replace a row with this 1463d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank rowsToReplace.add(row); 1464d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1465d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1466d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1467d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1468d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Go through rows needing replacement 1469d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (UntypedRow row: rowsToReplace) { 1470d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (NamedContentValues ncv: oldValues) { 1471d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = ncv.values; 1472d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Find a row that hasn't been used (i.e. doesn't match current rows) 1473d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (!cv.containsKey(FOUND_DATA_ROW)) { 1474d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // And update it 1475d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = new RowBuilder( 1476d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentProviderOperation 1477d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .newUpdate(addCallerIsSyncAdapterParameter( 1478d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank dataUriFromNamedContentValues(ncv))), 1479d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ncv); 1480d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank row.addValues(builder); 1481d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1482d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1483d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1484d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1485d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1486d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1487d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addOrganization(Entity entity, int type, String company, String title, 1488d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String department, String yomiCompanyName, String officeLocation) { 1489d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = typedRowBuilder(entity, Organization.CONTENT_ITEM_TYPE, type); 1490d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = builder.cv; 1491d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv != null && cvCompareString(cv, Organization.COMPANY, company) && 1492d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, Organization.PHONETIC_NAME, yomiCompanyName) && 1493d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, Organization.DEPARTMENT, department) && 1494d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, Organization.TITLE, title) && 1495d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cvCompareString(cv, Organization.OFFICE_LOCATION, officeLocation)) { 1496d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return; 1497d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1498d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Organization.TYPE, type); 1499d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Organization.COMPANY, company); 1500d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Organization.TITLE, title); 1501d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Organization.DEPARTMENT, department); 1502d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Organization.PHONETIC_NAME, yomiCompanyName); 1503d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Organization.OFFICE_LOCATION, officeLocation); 1504d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1505d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1506d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1507d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void addNote(Entity entity, String note) { 1508d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank RowBuilder builder = typedRowBuilder(entity, Note.CONTENT_ITEM_TYPE, -1); 1509d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = builder.cv; 1510d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (note == null) return; 1511d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank note = note.replaceAll("\r\n", "\n"); 1512d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv != null && cvCompareString(cv, Note.NOTE, note)) { 1513d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return; 1514d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1515d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1516d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Reject notes with nothing in them. Often, we get something from Outlook when 1517d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // nothing was ever entered. Sigh. 1518d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int len = note.length(); 1519d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int i = 0; 1520d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (; i < len; i++) { 1521d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank char c = note.charAt(i); 1522d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (!Character.isWhitespace(c)) { 1523d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1524d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1525d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1526d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (i == len) return; 1527d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1528d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank builder.withValue(Note.NOTE, note); 1529d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank add(builder.build()); 1530d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1531d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1532d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1533d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank /** 1534d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * Generate the uri for the data row associated with this NamedContentValues object 1535d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @param ncv the NamedContentValues object 1536d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank * @return a uri that can be used to refer to this row 1537d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank */ 1538d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public Uri dataUriFromNamedContentValues(NamedContentValues ncv) { 1539d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank long id = ncv.values.getAsLong(RawContacts._ID); 1540d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Uri dataUri = ContentUris.withAppendedId(ncv.uri, id); 1541d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return dataUri; 1542d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1543d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1544d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank @Override 1545d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public void cleanup() { 1546d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Mark the changed contacts dirty = 0 1547d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Permanently delete the user deletions 1548d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContactOperations ops = new ContactOperations(); 1549d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (Long id: mUpdatedIdList) { 1550d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.add(ContentProviderOperation 1551d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .newUpdate(ContentUris.withAppendedId(RawContacts.CONTENT_URI, id) 1552d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .buildUpon() 1553d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true") 1554d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .build()) 1555d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .withValue(RawContacts.DIRTY, 0).build()); 1556d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1557d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (Long id: mDeletedIdList) { 1558d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.add(ContentProviderOperation 1559d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .newDelete(ContentUris.withAppendedId(RawContacts.CONTENT_URI, id) 1560d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .buildUpon() 1561d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true") 1562d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .build()) 1563d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank .build()); 1564d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1565d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ops.execute(); 1566d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentResolver cr = mContext.getContentResolver(); 1567d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (mGroupsUsed) { 1568d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Make sure the title column is set for all of our groups 1569d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // And that all of our groups are visible 1570d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // TODO Perhaps the visible part should only happen when the group is created, but 1571d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // this is fine for now. 1572d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Uri groupsUri = uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI); 1573d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Cursor c = cr.query(groupsUri, new String[] {Groups.SOURCE_ID, Groups.TITLE}, 1574d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Groups.TITLE + " IS NULL", null, null); 1575d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues values = new ContentValues(); 1576d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank values.put(Groups.GROUP_VISIBLE, 1); 1577d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank try { 1578d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank while (c.moveToNext()) { 1579d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String sourceId = c.getString(0); 1580d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank values.put(Groups.TITLE, sourceId); 1581d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cr.update(uriWithAccountAndIsSyncAdapter(groupsUri), values, 1582d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Groups.SOURCE_ID + "=?", new String[] {sourceId}); 1583d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1584d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } finally { 1585d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank c.close(); 1586d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1587d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1588d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1589d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1590d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank @Override 1591d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public String getCollectionName() { 1592d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return "Contacts"; 1593d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1594d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1595d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendEmail(Serializer s, ContentValues cv, int count, String displayName) 1596d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank throws IOException { 1597d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Get both parts of the email address (a newly created one in the UI won't have a name) 1598d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String addr = cv.getAsString(Email.DATA); 1599d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String name = cv.getAsString(Email.DISPLAY_NAME); 1600d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (name == null) { 1601d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (displayName != null) { 1602d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank name = displayName; 1603d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else { 1604d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank name = addr; 1605d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1606d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1607d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Compose address from name and addr 1608d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (addr != null) { 1609d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String value; 1610d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Only send the raw email address for EAS 2.5 (Hotmail, in particular, chokes on 1611d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // an RFC822 address) 1612d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (mService.mProtocolVersionDouble < Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) { 1613d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank value = addr; 1614d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else { 1615d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank value = '\"' + name + "\" <" + addr + '>'; 1616d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1617d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (count < MAX_EMAIL_ROWS) { 1618d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(EMAIL_TAGS[count], value); 1619d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1620d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1621d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1622d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1623d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendIm(Serializer s, ContentValues cv, int count) throws IOException { 1624d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String value = cv.getAsString(Im.DATA); 1625d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (value == null) return; 1626d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (count < MAX_IM_ROWS) { 1627d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(IM_TAGS[count], value); 1628d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1629d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1630d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1631d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendOnePostal(Serializer s, ContentValues cv, int[] fieldNames) 1632d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank throws IOException{ 1633d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, StructuredPostal.CITY, fieldNames[0]); 1634d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, StructuredPostal.COUNTRY, fieldNames[1]); 1635d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, StructuredPostal.POSTCODE, fieldNames[2]); 1636d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, StructuredPostal.REGION, fieldNames[3]); 1637d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, StructuredPostal.STREET, fieldNames[4]); 1638d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1639d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1640d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendStructuredPostal(Serializer s, ContentValues cv) throws IOException { 1641d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank switch (cv.getAsInteger(StructuredPostal.TYPE)) { 1642d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case StructuredPostal.TYPE_HOME: 1643d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendOnePostal(s, cv, HOME_ADDRESS_TAGS); 1644d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1645d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case StructuredPostal.TYPE_WORK: 1646d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendOnePostal(s, cv, WORK_ADDRESS_TAGS); 1647d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1648d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case StructuredPostal.TYPE_OTHER: 1649d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendOnePostal(s, cv, OTHER_ADDRESS_TAGS); 1650d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1651d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank default: 1652d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1653d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1654d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1655d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1656d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendStringData(Serializer s, ContentValues cv, String column, int tag) 1657d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank throws IOException { 1658d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv.containsKey(column)) { 1659d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String value = cv.getAsString(column); 1660d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (!TextUtils.isEmpty(value)) { 1661d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(tag, value); 1662d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1663d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1664d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1665d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1666d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private String sendStructuredName(Serializer s, ContentValues cv) throws IOException { 1667d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String displayName = null; 1668d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, StructuredName.FAMILY_NAME, Tags.CONTACTS_LAST_NAME); 1669d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, StructuredName.GIVEN_NAME, Tags.CONTACTS_FIRST_NAME); 1670d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, StructuredName.MIDDLE_NAME, Tags.CONTACTS_MIDDLE_NAME); 1671d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, StructuredName.SUFFIX, Tags.CONTACTS_SUFFIX); 1672d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, StructuredName.PHONETIC_GIVEN_NAME, Tags.CONTACTS_YOMI_FIRST_NAME); 1673d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, StructuredName.PHONETIC_FAMILY_NAME, Tags.CONTACTS_YOMI_LAST_NAME); 1674d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, StructuredName.PREFIX, Tags.CONTACTS_TITLE); 1675d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return displayName; 1676d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1677d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1678d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendBusiness(Serializer s, ContentValues cv) throws IOException { 1679d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, EasBusiness.ACCOUNT_NAME, Tags.CONTACTS2_ACCOUNT_NAME); 1680d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, EasBusiness.CUSTOMER_ID, Tags.CONTACTS2_CUSTOMER_ID); 1681d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, EasBusiness.GOVERNMENT_ID, Tags.CONTACTS2_GOVERNMENT_ID); 1682d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1683d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1684d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendPersonal(Serializer s, ContentValues cv) throws IOException { 1685d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, EasPersonal.ANNIVERSARY, Tags.CONTACTS_ANNIVERSARY); 1686d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, EasPersonal.FILE_AS, Tags.CONTACTS_FILE_AS); 1687d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1688d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1689d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendBirthday(Serializer s, ContentValues cv) throws IOException { 1690d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, Event.START_DATE, Tags.CONTACTS_BIRTHDAY); 1691d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1692d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1693d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendPhoto(Serializer s, ContentValues cv) throws IOException { 1694d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv.containsKey(Photo.PHOTO)) { 1695d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank byte[] bytes = cv.getAsByteArray(Photo.PHOTO); 1696d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String pic = Base64.encodeToString(bytes, Base64.NO_WRAP); 1697d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS_PICTURE, pic); 1698d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else { 1699d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Send an empty tag, which signals the server to delete any pre-existing photo 1700d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.tag(Tags.CONTACTS_PICTURE); 1701d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1702d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1703d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1704d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendOrganization(Serializer s, ContentValues cv) throws IOException { 1705d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, Organization.TITLE, Tags.CONTACTS_JOB_TITLE); 1706d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, Organization.COMPANY, Tags.CONTACTS_COMPANY_NAME); 1707d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, Organization.DEPARTMENT, Tags.CONTACTS_DEPARTMENT); 1708d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, Organization.OFFICE_LOCATION, Tags.CONTACTS_OFFICE_LOCATION); 1709d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1710d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1711d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendNickname(Serializer s, ContentValues cv) throws IOException { 1712d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, Nickname.NAME, Tags.CONTACTS2_NICKNAME); 1713d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1714d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1715d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendWebpage(Serializer s, ContentValues cv) throws IOException { 1716d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStringData(s, cv, Website.URL, Tags.CONTACTS_WEBPAGE); 1717d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1718d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1719d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendNote(Serializer s, ContentValues cv) throws IOException { 1720d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Even when there is no local note, we must explicitly upsync an empty note, 1721d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // which is the only way to force the server to delete any pre-existing note. 1722d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String note = ""; 1723d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv.containsKey(Note.NOTE)) { 1724d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // EAS won't accept note data with raw newline characters 1725d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank note = cv.getAsString(Note.NOTE).replaceAll("\n", "\r\n"); 1726d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1727d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Format of upsync data depends on protocol version 1728d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (mService.mProtocolVersionDouble >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) { 1729d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.start(Tags.BASE_BODY); 1730d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.BASE_TYPE, Eas.BODY_PREFERENCE_TEXT).data(Tags.BASE_DATA, note); 1731d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.end(); 1732d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else { 1733d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS_BODY, note); 1734d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1735d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1736d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1737d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendChildren(Serializer s, ContentValues cv) throws IOException { 1738d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank boolean first = true; 1739d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (int i = 0; i < EasChildren.MAX_CHILDREN; i++) { 1740d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String row = EasChildren.ROWS[i]; 1741d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (cv.containsKey(row)) { 1742d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (first) { 1743d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.start(Tags.CONTACTS_CHILDREN); 1744d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank first = false; 1745d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1746d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS_CHILD, cv.getAsString(row)); 1747d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1748d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1749d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (!first) { 1750d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.end(); 1751d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1752d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1753d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1754d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendPhone(Serializer s, ContentValues cv, int workCount, int homeCount) 1755d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank throws IOException { 1756d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String value = cv.getAsString(Phone.NUMBER); 1757d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (value == null) return; 1758d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank switch (cv.getAsInteger(Phone.TYPE)) { 1759d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Phone.TYPE_WORK: 1760d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (workCount < MAX_PHONE_ROWS) { 1761d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(WORK_PHONE_TAGS[workCount], value); 1762d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1763d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1764d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Phone.TYPE_MMS: 1765d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS2_MMS, value); 1766d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1767d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Phone.TYPE_ASSISTANT: 1768d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS_ASSISTANT_TELEPHONE_NUMBER, value); 1769d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1770d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Phone.TYPE_FAX_WORK: 1771d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS_BUSINESS_FAX_NUMBER, value); 1772d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1773d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Phone.TYPE_COMPANY_MAIN: 1774d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS2_COMPANY_MAIN_PHONE, value); 1775d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1776d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Phone.TYPE_HOME: 1777d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (homeCount < MAX_PHONE_ROWS) { 1778d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(HOME_PHONE_TAGS[homeCount], value); 1779d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1780d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1781d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Phone.TYPE_MOBILE: 1782d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS_MOBILE_TELEPHONE_NUMBER, value); 1783d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1784d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Phone.TYPE_CAR: 1785d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS_CAR_TELEPHONE_NUMBER, value); 1786d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1787d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Phone.TYPE_PAGER: 1788d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS_PAGER_NUMBER, value); 1789d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1790d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Phone.TYPE_RADIO: 1791d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS_RADIO_TELEPHONE_NUMBER, value); 1792d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1793d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Phone.TYPE_FAX_HOME: 1794d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS_HOME_FAX_NUMBER, value); 1795d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1796d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank default: 1797d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1798d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1799d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1800d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1801d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void sendRelation(Serializer s, ContentValues cv) throws IOException { 1802d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String value = cv.getAsString(Relation.DATA); 1803d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (value == null) return; 1804d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank switch (cv.getAsInteger(Relation.TYPE)) { 1805d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Relation.TYPE_ASSISTANT: 1806d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS_ASSISTANT_NAME, value); 1807d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1808d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Relation.TYPE_MANAGER: 1809d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS2_MANAGER_NAME, value); 1810d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1811d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank case Relation.TYPE_SPOUSE: 1812d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS_SPOUSE, value); 1813d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1814d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank default: 1815d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank break; 1816d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1817d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1818d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1819d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank private void dirtyContactsWithinDirtyGroups() { 1820d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentResolver cr = mService.mContentResolver; 1821d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Cursor c = cr.query(uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI), 1822d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank GROUPS_ID_PROJECTION, Groups.DIRTY + "=1", null, null); 1823d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank try { 1824d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (c.getCount() > 0) { 1825d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String[] updateArgs = new String[1]; 1826d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues updateValues = new ContentValues(); 1827d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank while (c.moveToNext()) { 1828d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // For each, "touch" all data rows with this group id; this will mark contacts 1829d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // in this group as dirty (per ContactsContract). We will then know to upload 1830d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // them to the server with the modified group information 1831d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank long id = c.getLong(0); 1832d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank updateValues.put(GroupMembership.GROUP_ROW_ID, id); 1833d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank updateArgs[0] = Long.toString(id); 1834d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cr.update(Data.CONTENT_URI, updateValues, 1835d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank MIMETYPE_GROUP_MEMBERSHIP_AND_ID_EQUALS, updateArgs); 1836d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1837d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Really delete groups that are marked deleted 1838d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cr.delete(uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI), Groups.DELETED + "=1", 1839d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank null); 1840d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Clear the dirty flag for all of our groups 1841d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank updateValues.clear(); 1842d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank updateValues.put(Groups.DIRTY, 0); 1843d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cr.update(uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI), updateValues, null, 1844d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank null); 1845d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1846d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } finally { 1847d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank c.close(); 1848d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1849d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1850d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1851d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank @Override 1852d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank public boolean sendLocalChanges(Serializer s) throws IOException { 1853d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentResolver cr = mService.mContentResolver; 1854d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1855d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Find any groups of ours that are dirty and dirty those groups' members 1856d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank dirtyContactsWithinDirtyGroups(); 1857d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1858d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // First, let's find Contacts that have changed. 1859d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Uri uri = uriWithAccountAndIsSyncAdapter(RawContactsEntity.CONTENT_URI); 1860d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (getSyncKey().equals("0")) { 1861d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return false; 1862d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1863d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1864d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Get them all atomically 1865d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank EntityIterator ei = RawContacts.newEntityIterator( 1866d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cr.query(uri, null, RawContacts.DIRTY + "=1", null, null)); 1867d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cidValues = new ContentValues(); 1868d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank try { 1869d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank boolean first = true; 1870d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank final Uri rawContactUri = addCallerIsSyncAdapterParameter(RawContacts.CONTENT_URI); 1871d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank while (ei.hasNext()) { 1872d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Entity entity = ei.next(); 1873d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // For each of these entities, create the change commands 1874d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues entityValues = entity.getEntityValues(); 1875d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String serverId = entityValues.getAsString(RawContacts.SOURCE_ID); 1876d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ArrayList<Integer> groupIds = new ArrayList<Integer>(); 1877d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (first) { 1878d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.start(Tags.SYNC_COMMANDS); 1879d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank userLog("Sending Contacts changes to the server"); 1880d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank first = false; 1881d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1882d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (serverId == null) { 1883d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // This is a new contact; create a clientId 1884d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String clientId = "new_" + mMailbox.mId + '_' + System.currentTimeMillis(); 1885d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank userLog("Creating new contact with clientId: ", clientId); 1886d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.start(Tags.SYNC_ADD).data(Tags.SYNC_CLIENT_ID, clientId); 1887d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // And save it in the raw contact 1888d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cidValues.put(RawContacts.SYNC1, clientId); 1889d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cr.update(ContentUris. 1890d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank withAppendedId(rawContactUri, 1891d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank entityValues.getAsLong(RawContacts._ID)), 1892d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank cidValues, null, null); 1893d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else { 1894d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (entityValues.getAsInteger(RawContacts.DELETED) == 1) { 1895d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank userLog("Deleting contact with serverId: ", serverId); 1896d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.start(Tags.SYNC_DELETE).data(Tags.SYNC_SERVER_ID, serverId).end(); 1897d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mDeletedIdList.add(entityValues.getAsLong(RawContacts._ID)); 1898d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank continue; 1899d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1900d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank userLog("Upsync change to contact with serverId: " + serverId); 1901d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.start(Tags.SYNC_CHANGE).data(Tags.SYNC_SERVER_ID, serverId); 1902d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1903d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.start(Tags.SYNC_APPLICATION_DATA); 1904d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Write out the data here 1905d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int imCount = 0; 1906d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int emailCount = 0; 1907d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int homePhoneCount = 0; 1908d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int workPhoneCount = 0; 1909d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String displayName = null; 1910d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ArrayList<ContentValues> emailValues = new ArrayList<ContentValues>(); 1911d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (NamedContentValues ncv: entity.getSubValues()) { 1912d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ContentValues cv = ncv.values; 1913d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank String mimeType = cv.getAsString(Data.MIMETYPE); 1914d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (mimeType.equals(Email.CONTENT_ITEM_TYPE)) { 1915d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank emailValues.add(cv); 1916d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(Nickname.CONTENT_ITEM_TYPE)) { 1917d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendNickname(s, cv); 1918d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(EasChildren.CONTENT_ITEM_TYPE)) { 1919d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendChildren(s, cv); 1920d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(EasBusiness.CONTENT_ITEM_TYPE)) { 1921d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendBusiness(s, cv); 1922d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(Website.CONTENT_ITEM_TYPE)) { 1923d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendWebpage(s, cv); 1924d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(EasPersonal.CONTENT_ITEM_TYPE)) { 1925d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendPersonal(s, cv); 1926d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(Phone.CONTENT_ITEM_TYPE)) { 1927d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendPhone(s, cv, workPhoneCount, homePhoneCount); 1928d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank int type = cv.getAsInteger(Phone.TYPE); 1929d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (type == Phone.TYPE_HOME) homePhoneCount++; 1930d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (type == Phone.TYPE_WORK) workPhoneCount++; 1931d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(Relation.CONTENT_ITEM_TYPE)) { 1932d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendRelation(s, cv); 1933d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(StructuredName.CONTENT_ITEM_TYPE)) { 1934d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank displayName = sendStructuredName(s, cv); 1935d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(StructuredPostal.CONTENT_ITEM_TYPE)) { 1936d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendStructuredPostal(s, cv); 1937d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(Organization.CONTENT_ITEM_TYPE)) { 1938d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendOrganization(s, cv); 1939d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(Im.CONTENT_ITEM_TYPE)) { 1940d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendIm(s, cv, imCount++); 1941d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(Event.CONTENT_ITEM_TYPE)) { 1942d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Integer eventType = cv.getAsInteger(Event.TYPE); 1943d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (eventType != null && eventType.equals(Event.TYPE_BIRTHDAY)) { 1944d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendBirthday(s, cv); 1945d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1946d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(GroupMembership.CONTENT_ITEM_TYPE)) { 1947d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // We must gather these, and send them together (below) 1948d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank groupIds.add(cv.getAsInteger(GroupMembership.GROUP_ROW_ID)); 1949d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(Note.CONTENT_ITEM_TYPE)) { 1950d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendNote(s, cv); 1951d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else if (mimeType.equals(Photo.CONTENT_ITEM_TYPE)) { 1952d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendPhoto(s, cv); 1953d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } else { 1954d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank userLog("Contacts upsync, unknown data: ", mimeType); 1955d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1956d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1957d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1958d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // We do the email rows last, because we need to make sure we've found the 1959d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // displayName (if one exists); this would be in a StructuredName rnow 1960d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (ContentValues cv: emailValues) { 1961d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank sendEmail(s, cv, emailCount++, displayName); 1962d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1963d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1964d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Now, we'll send up groups, if any 1965d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (!groupIds.isEmpty()) { 1966d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank boolean groupFirst = true; 1967d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank for (int id: groupIds) { 1968d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Since we get id's from the provider, we need to find their names 1969d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank Cursor c = cr.query(ContentUris.withAppendedId(Groups.CONTENT_URI, id), 1970d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank GROUP_TITLE_PROJECTION, null, null, null); 1971d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank try { 1972d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank // Presumably, this should always succeed, but ... 1973d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (c.moveToFirst()) { 1974d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (groupFirst) { 1975d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.start(Tags.CONTACTS_CATEGORIES); 1976d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank groupFirst = false; 1977d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1978d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.data(Tags.CONTACTS_CATEGORY, c.getString(0)); 1979d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1980d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } finally { 1981d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank c.close(); 1982d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1983d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1984d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (!groupFirst) { 1985d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.end(); 1986d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1987d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1988d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.end().end(); // ApplicationData & Change 1989d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank mUpdatedIdList.add(entityValues.getAsLong(RawContacts._ID)); 1990d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1991d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank if (!first) { 1992d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank s.end(); // Commands 1993d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1994d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } finally { 1995d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank ei.close(); 1996d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 1997d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank 1998d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank return false; 1999d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank } 2000d2e4d4675d04e78591ebd38fd084fc2cdbe144a0Marc Blank} 2001