/** * Build a list of {@link ContentProviderOperation} that will transform the current "before" * {@link Entity} state into the modified state which this {@link RawContactDelta} represents. */ public void buildDiff(ArrayList<ContentProviderOperation> buildInto) { final int firstIndex = buildInto.size(); final boolean isContactInsert = mValues.isInsert(); final boolean isContactDelete = mValues.isDelete(); final boolean isContactUpdate = !isContactInsert && !isContactDelete; final Long beforeId = mValues.getId(); Builder builder; if (isContactInsert) { // TODO: for now simply disabling aggregation when a new contact is // created on the phone. In the future, will show aggregation suggestions // after saving the contact. mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED); } // Build possible operation at Contact level builder = mValues.buildDiff(mContactsQueryUri); possibleAdd(buildInto, builder); // Build operations for all children for (ArrayList<ValuesDelta> mimeEntries : mEntries.values()) { for (ValuesDelta child : mimeEntries) { // Ignore children if parent was deleted if (isContactDelete) continue; // Use the profile data URI if the contact is the profile. if (mContactsQueryUri.equals(Profile.CONTENT_RAW_CONTACTS_URI)) { builder = child.buildDiff( Uri.withAppendedPath(Profile.CONTENT_URI, RawContacts.Data.CONTENT_DIRECTORY)); } else { builder = child.buildDiff(Data.CONTENT_URI); } if (child.isInsert()) { if (isContactInsert) { // Parent is brand new insert, so back-reference _id builder.withValueBackReference(Data.RAW_CONTACT_ID, firstIndex); } else { // Inserting under existing, so fill with known _id builder.withValue(Data.RAW_CONTACT_ID, beforeId); } } else if (isContactInsert && builder != null) { // Child must be insert when Contact insert throw new IllegalArgumentException("When parent insert, child must be also"); } possibleAdd(buildInto, builder); } } final boolean addedOperations = buildInto.size() > firstIndex; if (addedOperations && isContactUpdate) { // Suspend aggregation while persisting updates builder = buildSetAggregationMode(beforeId, RawContacts.AGGREGATION_MODE_SUSPENDED); buildInto.add(firstIndex, builder.build()); // Restore aggregation mode as last operation builder = buildSetAggregationMode(beforeId, RawContacts.AGGREGATION_MODE_DEFAULT); buildInto.add(builder.build()); } else if (isContactInsert) { // Restore aggregation mode as last operation builder = ContentProviderOperation.newUpdate(mContactsQueryUri); builder.withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DEFAULT); builder.withSelection(RawContacts._ID + "=?", new String[1]); builder.withSelectionBackReference(0, firstIndex); buildInto.add(builder.build()); } }