DataRowHandler.java revision 08fb8384ccb36de3d3d046e287fe5c43c1f85faf
1f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov/* 2f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * Copyright (C) 2010 The Android Open Source Project 3f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * 4f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * use this file except in compliance with the License. You may obtain a copy of 6f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * the License at 7f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * 8f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * http://www.apache.org/licenses/LICENSE-2.0 9f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * 10f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * Unless required by applicable law or agreed to in writing, software 11f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * License for the specific language governing permissions and limitations under 14f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * the License 15f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov */ 16f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikovpackage com.android.providers.contacts; 17f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 18f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikovimport android.content.ContentValues; 196d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikovimport android.content.Context; 20f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikovimport android.database.Cursor; 21f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikovimport android.database.sqlite.SQLiteDatabase; 22f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 23f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 24f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 25f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 26f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 27f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikovimport android.provider.ContactsContract.Data; 28f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikovimport android.text.TextUtils; 2938210445730ee04c351c7cc1b3800cfe23e34325Makoto Onukiimport com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; 3038210445730ee04c351c7cc1b3800cfe23e34325Makoto Onukiimport com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns; 3138210445730ee04c351c7cc1b3800cfe23e34325Makoto Onukiimport com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 3238210445730ee04c351c7cc1b3800cfe23e34325Makoto Onukiimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 33aa18c233fdec3359c5231d4a5f61188446bf5d6fZheng Fuimport com.android.providers.contacts.aggregation.AbstractContactAggregator; 3438210445730ee04c351c7cc1b3800cfe23e34325Makoto Onuki 35f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov/** 36f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * Handles inserts and update for a specific Data type. 37f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov */ 38f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikovpublic abstract class DataRowHandler { 39f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 40f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public interface DataDeleteQuery { 41f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 42f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 43f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 44f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov DataColumns.CONCRETE_ID, 45f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov MimetypesColumns.MIMETYPE, 46f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Data.RAW_CONTACT_ID, 47f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Data.IS_PRIMARY, 48f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Data.DATA1, 49f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov }; 50f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 51f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 52f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Data._ID, 53f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov MimetypesColumns.MIMETYPE, 54f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Data.RAW_CONTACT_ID, 55f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Data.IS_PRIMARY, 56f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Data.DATA1, 57f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov }; 58f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 59f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public static final int _ID = 0; 60f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public static final int MIMETYPE = 1; 61f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 62f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public static final int IS_PRIMARY = 3; 63f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public static final int DATA1 = 4; 64f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 65f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 66f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public interface DataUpdateQuery { 67f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 68f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 69f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov int _ID = 0; 70f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov int RAW_CONTACT_ID = 1; 71f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov int MIMETYPE = 2; 72f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 73f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 746d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov protected final Context mContext; 75f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov protected final ContactsDatabaseHelper mDbHelper; 76aa18c233fdec3359c5231d4a5f61188446bf5d6fZheng Fu protected final AbstractContactAggregator mContactAggregator; 77f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov protected String[] mSelectionArgs1 = new String[1]; 78f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov protected final String mMimetype; 79f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov protected long mMimetypeId; 80f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 81f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov @SuppressWarnings("all") 826d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov public DataRowHandler(Context context, ContactsDatabaseHelper dbHelper, 83aa18c233fdec3359c5231d4a5f61188446bf5d6fZheng Fu AbstractContactAggregator aggregator, String mimetype) { 846d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov mContext = context; 85f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mDbHelper = dbHelper; 86f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mContactAggregator = aggregator; 87f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mMimetype = mimetype; 88f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 89f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // To ensure the data column position. This is dead code if properly configured. 90f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 91f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 92f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov || Email.DATA != Data.DATA1) { 93f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 94f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov + " data is not in DATA1 column"); 95f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 96f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 97f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 98f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov protected long getMimeTypeId() { 99f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (mMimetypeId == 0) { 100f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mMimetypeId = mDbHelper.getMimeTypeId(mMimetype); 101f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 102f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov return mMimetypeId; 103f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 104f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 105f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov /** 106f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * Inserts a row into the {@link Data} table. 107f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov */ 108f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public long insert(SQLiteDatabase db, TransactionContext txContext, long rawContactId, 109f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov ContentValues values) { 110f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 111f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 112f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final Integer primary = values.getAsInteger(Data.IS_PRIMARY); 113f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final Integer superPrimary = values.getAsInteger(Data.IS_SUPER_PRIMARY); 114f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if ((primary != null && primary != 0) || (superPrimary != null && superPrimary != 0)) { 115f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final long mimeTypeId = getMimeTypeId(); 116f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mDbHelper.setIsPrimary(rawContactId, dataId, mimeTypeId); 11708fb8384ccb36de3d3d046e287fe5c43c1f85fafZheng Fu txContext.markRawContactMetadataDirty(rawContactId, /* isMetadataSyncAdapter =*/false); 118f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 119f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // We also have to make sure that no other data item on this raw_contact is 120f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // configured super primary 121f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (superPrimary != null) { 122f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (superPrimary != 0) { 123f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mDbHelper.setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 124f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } else { 125f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mDbHelper.clearSuperPrimary(rawContactId, mimeTypeId); 126f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 127f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } else { 128f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // if there is already another data item configured as super-primary, 129f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // take over the flag (which will automatically remove it from the other item) 130f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (mDbHelper.rawContactHasSuperPrimary(rawContactId, mimeTypeId)) { 131f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mDbHelper.setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 132f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 133f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 134f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 135f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 136f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov if (containsSearchableColumns(values)) { 137f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov txContext.invalidateSearchIndexForRawContact(rawContactId); 138f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 139f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 140f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov return dataId; 141f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 142f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 143f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov /** 144f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 145f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * the current data. 146f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * 147f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * @return true if update changed something 148f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov */ 149f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public boolean update(SQLiteDatabase db, TransactionContext txContext, 15008fb8384ccb36de3d3d046e287fe5c43c1f85fafZheng Fu ContentValues values, Cursor c, boolean callerIsSyncAdapter, 15108fb8384ccb36de3d3d046e287fe5c43c1f85fafZheng Fu boolean callerIsMetadataSyncAdapter) { 152f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 153f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 154f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 15508fb8384ccb36de3d3d046e287fe5c43c1f85fafZheng Fu handlePrimaryAndSuperPrimary(txContext, values, dataId, rawContactId, 15608fb8384ccb36de3d3d046e287fe5c43c1f85fafZheng Fu callerIsMetadataSyncAdapter); 157f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 158f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (values.size() > 0) { 159f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 160f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov db.update(Tables.DATA, values, Data._ID + " =?", mSelectionArgs1); 161f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 162f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 163f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov if (containsSearchableColumns(values)) { 164f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov txContext.invalidateSearchIndexForRawContact(rawContactId); 165f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 166f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 1678ed367fdc0b086d54c489f68d555e2f0a4035f63Chiao Cheng txContext.markRawContactDirtyAndChanged(rawContactId, callerIsSyncAdapter); 168f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 169f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov return true; 170f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 171f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 172f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public boolean hasSearchableData() { 173f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov return false; 174f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 175f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 176f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public boolean containsSearchableColumns(ContentValues values) { 177f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov return false; 178f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 179f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 180f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public void appendSearchableData(SearchIndexManager.IndexBuilder builder) { 181f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 182f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 183f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov /** 184f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * Ensures that all super-primary and primary flags of this raw_contact are 185f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * configured correctly 186f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov */ 18708fb8384ccb36de3d3d046e287fe5c43c1f85fafZheng Fu private void handlePrimaryAndSuperPrimary(TransactionContext txContext, ContentValues values, 18808fb8384ccb36de3d3d046e287fe5c43c1f85fafZheng Fu long dataId, long rawContactId, boolean callerIsMetadataSyncAdapter) { 189ee1267f05b98218d26f39875949cbc66a8a9b71dJay Shrauner final boolean hasPrimary = values.getAsInteger(Data.IS_PRIMARY) != null; 190ee1267f05b98218d26f39875949cbc66a8a9b71dJay Shrauner final boolean hasSuperPrimary = values.getAsInteger(Data.IS_SUPER_PRIMARY) != null; 191f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 192f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // Nothing to do? Bail out early 193f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (!hasPrimary && !hasSuperPrimary) return; 194f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 19508fb8384ccb36de3d3d046e287fe5c43c1f85fafZheng Fu txContext.markRawContactMetadataDirty(rawContactId, callerIsMetadataSyncAdapter); 19608fb8384ccb36de3d3d046e287fe5c43c1f85fafZheng Fu 197f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final long mimeTypeId = getMimeTypeId(); 198f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 199f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // Check if we want to clear values 200f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final boolean clearPrimary = hasPrimary && 201f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov values.getAsInteger(Data.IS_PRIMARY) == 0; 202f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final boolean clearSuperPrimary = hasSuperPrimary && 203f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov values.getAsInteger(Data.IS_SUPER_PRIMARY) == 0; 204f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 205f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (clearPrimary || clearSuperPrimary) { 206f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // Test whether these values are currently set 207f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 208f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final String[] cols = new String[] { Data.IS_PRIMARY, Data.IS_SUPER_PRIMARY }; 209f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final Cursor c = mDbHelper.getReadableDatabase().query(Tables.DATA, 210f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov cols, Data._ID + "=?", mSelectionArgs1, null, null, null); 211f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov try { 212f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (c.moveToFirst()) { 213f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final boolean isPrimary = c.getInt(0) != 0; 214f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final boolean isSuperPrimary = c.getInt(1) != 0; 215f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // Clear values if they are currently set 216f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (isSuperPrimary) { 217f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mDbHelper.clearSuperPrimary(rawContactId, mimeTypeId); 218f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 219f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (clearPrimary && isPrimary) { 220f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mDbHelper.setIsPrimary(rawContactId, -1, mimeTypeId); 221f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 222f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 223f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } finally { 224f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov c.close(); 225f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 226f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } else { 227f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // Check if we want to set values 228f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final boolean setPrimary = hasPrimary && 229f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov values.getAsInteger(Data.IS_PRIMARY) != 0; 230f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final boolean setSuperPrimary = hasSuperPrimary && 231f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov values.getAsInteger(Data.IS_SUPER_PRIMARY) != 0; 232f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (setSuperPrimary) { 233f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // Set both super primary and primary 234f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mDbHelper.setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 235f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mDbHelper.setIsPrimary(rawContactId, dataId, mimeTypeId); 236f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } else if (setPrimary) { 237f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // Primary was explicitly set, but super-primary was not. 238f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // In this case we set super-primary on this data item, if 239f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // any data item of the same raw-contact already is super-primary 240f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (mDbHelper.rawContactHasSuperPrimary(rawContactId, mimeTypeId)) { 241f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mDbHelper.setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 242f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 243f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mDbHelper.setIsPrimary(rawContactId, dataId, mimeTypeId); 244f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 245f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 246f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 247f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov // Now that we've taken care of clearing this, remove it from "values". 248f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 249f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 250f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 251f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 252f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public int delete(SQLiteDatabase db, TransactionContext txContext, Cursor c) { 253f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 254f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 255f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 256f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 257f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=?", mSelectionArgs1); 258f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 259f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov db.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=?", mSelectionArgs1); 260f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (count != 0 && primary) { 261f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov fixPrimary(db, rawContactId); 26208fb8384ccb36de3d3d046e287fe5c43c1f85fafZheng Fu txContext.markRawContactMetadataDirty(rawContactId, /* isMetadataSyncAdapter =*/false); 263f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 264f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 265f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov if (hasSearchableData()) { 266f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov txContext.invalidateSearchIndexForRawContact(rawContactId); 267f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov } 268f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov 269f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov return count; 270f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 271f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 272f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 273f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 274f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long primaryId = -1; 275f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov int primaryType = -1; 276f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 277f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = db.query(DataDeleteQuery.TABLE, 278f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov DataDeleteQuery.CONCRETE_COLUMNS, 279f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Data.RAW_CONTACT_ID + "=?" + 280f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov " AND " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId, 281f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mSelectionArgs1, null, null, null); 282f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov try { 283f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov while (c.moveToNext()) { 284f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 285f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 286f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 287f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov primaryId = dataId; 288f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov primaryType = type; 289f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 290f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 291f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } finally { 292f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov c.close(); 293f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 294f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (primaryId != -1) { 295f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mDbHelper.setIsPrimary(rawContactId, primaryId, mimeTypeId); 296f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 297f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 298f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 299f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov /** 300f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 301f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * row. Lower number represents higher priority. 302f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov */ 303f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov protected int getTypeRank(int type) { 304f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov return 0; 305f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 306f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 307f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, TransactionContext txContext, 308f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long rawContactId) { 309f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (!isNewRawContact(txContext, rawContactId)) { 3108ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov mDbHelper.updateRawContactDisplayName(db, rawContactId); 311f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(db, rawContactId); 312f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 313f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 314f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 315f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov private boolean isNewRawContact(TransactionContext txContext, long rawContactId) { 316f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov return txContext.isNewRawContact(rawContactId); 317f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 318f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 319f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov /** 320f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * Return set of values, using current values at given {@link Data#_ID} 321f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * as baseline, but augmented with any updates. Returns null if there is 322f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * no change. 323f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov */ 324f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 325f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov ContentValues update) { 326f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov boolean changing = false; 327f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final ContentValues values = new ContentValues(); 328f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 329f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=?", 330f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mSelectionArgs1, null, null, null); 331f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov try { 332f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (cursor.moveToFirst()) { 333f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov for (int i = 0; i < cursor.getColumnCount(); i++) { 334f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final String key = cursor.getColumnName(i); 335f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final String value = cursor.getString(i); 336f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (!changing && update.containsKey(key)) { 337f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Object newValue = update.get(key); 338f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String newString = newValue == null ? null : newValue.toString(); 339f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov changing |= !TextUtils.equals(newString, value); 340f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 341f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov values.put(key, value); 342f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 343f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 344f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } finally { 345f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov cursor.close(); 346f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 347f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (!changing) { 348f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov return null; 349f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 350f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 351f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov values.putAll(update); 352f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov return values; 353f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 354f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 355bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov public void triggerAggregation(TransactionContext txContext, long rawContactId) { 356bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mContactAggregator.triggerAggregation(txContext, rawContactId); 357f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 358f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 359f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov /** 360f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * Test all against {@link TextUtils#isEmpty(CharSequence)}. 361f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov */ 362f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public boolean areAllEmpty(ContentValues values, String[] keys) { 363f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov for (String key : keys) { 364f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (!TextUtils.isEmpty(values.getAsString(key))) { 365f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov return false; 366f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 367f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 368f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov return true; 369f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 370f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 371f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov /** 372f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov * Returns true if a value (possibly null) is specified for at least one of the supplied keys. 373f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov */ 374f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov public boolean areAnySpecified(ContentValues values, String[] keys) { 375f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov for (String key : keys) { 376f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov if (values.containsKey(key)) { 377f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov return true; 378f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 379f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 380f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov return false; 381f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 382f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov} 383