1ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana/* 2ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Copyright (C) 2009 The Android Open Source Project 3ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * 4ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Licensed under the Apache License, Version 2.0 (the "License"); 5ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * you may not use this file except in compliance with the License. 6ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * You may obtain a copy of the License at 7ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * 8ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * http://www.apache.org/licenses/LICENSE-2.0 9ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * 10ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Unless required by applicable law or agreed to in writing, software 11ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * distributed under the License is distributed on an "AS IS" BASIS, 12ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * See the License for the specific language governing permissions and 14ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * limitations under the License. 15ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 16ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 17ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintanapackage android.content; 18ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 19d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevotimport android.content.ContentProvider; 20ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintanaimport android.database.Cursor; 2108b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkeyimport android.net.Uri; 228943737692169f564cd34a9c8d471f3a5d438712Fred Quintanaimport android.os.Parcel; 2308b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkeyimport android.os.Parcelable; 2408b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkeyimport android.text.TextUtils; 2535abad216da8a49128c3899a206c15d44c471617Ken Shirriffimport android.util.Log; 26ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 2708b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkeyimport java.util.ArrayList; 288943737692169f564cd34a9c8d471f3a5d438712Fred Quintanaimport java.util.HashMap; 2908b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkeyimport java.util.Map; 30ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 318943737692169f564cd34a9c8d471f3a5d438712Fred Quintanapublic class ContentProviderOperation implements Parcelable { 32bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey /** @hide exposed for unit tests */ 33bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey public final static int TYPE_INSERT = 1; 34bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey /** @hide exposed for unit tests */ 35bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey public final static int TYPE_UPDATE = 2; 36bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey /** @hide exposed for unit tests */ 37bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey public final static int TYPE_DELETE = 3; 38bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey /** @hide exposed for unit tests */ 3908b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey public final static int TYPE_ASSERT = 4; 40ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 41ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final int mType; 42ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final Uri mUri; 43ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final String mSelection; 44ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final String[] mSelectionArgs; 45ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final ContentValues mValues; 46ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final Integer mExpectedCount; 47ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final ContentValues mValuesBackReferences; 48ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final Map<Integer, Integer> mSelectionArgsBackReferences; 4956f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana private final boolean mYieldAllowed; 50ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 5135abad216da8a49128c3899a206c15d44c471617Ken Shirriff private final static String TAG = "ContentProviderOperation"; 5235abad216da8a49128c3899a206c15d44c471617Ken Shirriff 53ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 54ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Creates a {@link ContentProviderOperation} by copying the contents of a 55ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * {@link Builder}. 56ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 57ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private ContentProviderOperation(Builder builder) { 58ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mType = builder.mType; 59ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mUri = builder.mUri; 60ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mValues = builder.mValues; 61ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mSelection = builder.mSelection; 62ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mSelectionArgs = builder.mSelectionArgs; 63ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mExpectedCount = builder.mExpectedCount; 64ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mSelectionArgsBackReferences = builder.mSelectionArgsBackReferences; 65ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mValuesBackReferences = builder.mValuesBackReferences; 6656f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana mYieldAllowed = builder.mYieldAllowed; 67ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 68ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 6903d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana private ContentProviderOperation(Parcel source) { 708943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mType = source.readInt(); 718943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mUri = Uri.CREATOR.createFromParcel(source); 728943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mValues = source.readInt() != 0 ? ContentValues.CREATOR.createFromParcel(source) : null; 738943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mSelection = source.readInt() != 0 ? source.readString() : null; 748943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mSelectionArgs = source.readInt() != 0 ? source.readStringArray() : null; 758943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mExpectedCount = source.readInt() != 0 ? source.readInt() : null; 768943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mValuesBackReferences = source.readInt() != 0 778943737692169f564cd34a9c8d471f3a5d438712Fred Quintana ? ContentValues.CREATOR.createFromParcel(source) 788943737692169f564cd34a9c8d471f3a5d438712Fred Quintana : null; 798943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mSelectionArgsBackReferences = source.readInt() != 0 808943737692169f564cd34a9c8d471f3a5d438712Fred Quintana ? new HashMap<Integer, Integer>() 818943737692169f564cd34a9c8d471f3a5d438712Fred Quintana : null; 828943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (mSelectionArgsBackReferences != null) { 838943737692169f564cd34a9c8d471f3a5d438712Fred Quintana final int count = source.readInt(); 848943737692169f564cd34a9c8d471f3a5d438712Fred Quintana for (int i = 0; i < count; i++) { 858943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mSelectionArgsBackReferences.put(source.readInt(), source.readInt()); 868943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 878943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 8856f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana mYieldAllowed = source.readInt() != 0; 898943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 908943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 91d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot /** @hide */ 92d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot public ContentProviderOperation(ContentProviderOperation cpo, boolean removeUserIdFromUri) { 93d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot mType = cpo.mType; 94d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot if (removeUserIdFromUri) { 95d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot mUri = ContentProvider.getUriWithoutUserId(cpo.mUri); 96d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot } else { 97d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot mUri = cpo.mUri; 98d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot } 99d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot mValues = cpo.mValues; 100d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot mSelection = cpo.mSelection; 101d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot mSelectionArgs = cpo.mSelectionArgs; 102d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot mExpectedCount = cpo.mExpectedCount; 103d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot mSelectionArgsBackReferences = cpo.mSelectionArgsBackReferences; 104d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot mValuesBackReferences = cpo.mValuesBackReferences; 105d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot mYieldAllowed = cpo.mYieldAllowed; 106d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot } 107d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot 108d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot /** @hide */ 109d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot public ContentProviderOperation getWithoutUserIdInUri() { 110d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot if (ContentProvider.uriHasUserId(mUri)) { 111d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot return new ContentProviderOperation(this, true); 112d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot } 113d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot return this; 114d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot } 115d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot 1168943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public void writeToParcel(Parcel dest, int flags) { 1178943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(mType); 1188943737692169f564cd34a9c8d471f3a5d438712Fred Quintana Uri.writeToParcel(dest, mUri); 1198943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (mValues != null) { 1208943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(1); 1218943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mValues.writeToParcel(dest, 0); 1228943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } else { 1238943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(0); 1248943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1258943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (mSelection != null) { 1268943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(1); 1278943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeString(mSelection); 1288943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } else { 1298943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(0); 1308943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1318943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (mSelectionArgs != null) { 1328943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(1); 1338943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeStringArray(mSelectionArgs); 1348943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } else { 1358943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(0); 1368943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1378943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (mExpectedCount != null) { 1388943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(1); 1398943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(mExpectedCount); 1408943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } else { 1418943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(0); 1428943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1438943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (mValuesBackReferences != null) { 1448943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(1); 1458943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mValuesBackReferences.writeToParcel(dest, 0); 1468943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } else { 1478943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(0); 1488943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1498943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (mSelectionArgsBackReferences != null) { 1508943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(1); 1518943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(mSelectionArgsBackReferences.size()); 1528943737692169f564cd34a9c8d471f3a5d438712Fred Quintana for (Map.Entry<Integer, Integer> entry : mSelectionArgsBackReferences.entrySet()) { 1538943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(entry.getKey()); 1548943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(entry.getValue()); 1558943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1568943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } else { 1578943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(0); 1588943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 15956f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana dest.writeInt(mYieldAllowed ? 1 : 0); 1608943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1618943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 162ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 163ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Create a {@link Builder} suitable for building an insert {@link ContentProviderOperation}. 164ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param uri The {@link Uri} that is the target of the insert. 165ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return a {@link Builder} 166ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 167ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public static Builder newInsert(Uri uri) { 168ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return new Builder(TYPE_INSERT, uri); 169ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 170ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 171ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 172ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Create a {@link Builder} suitable for building an update {@link ContentProviderOperation}. 173ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param uri The {@link Uri} that is the target of the update. 174ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return a {@link Builder} 175ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 176ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public static Builder newUpdate(Uri uri) { 177ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return new Builder(TYPE_UPDATE, uri); 178ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 179ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 180ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 181ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Create a {@link Builder} suitable for building a delete {@link ContentProviderOperation}. 182ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param uri The {@link Uri} that is the target of the delete. 183ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return a {@link Builder} 184ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 185ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public static Builder newDelete(Uri uri) { 186ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return new Builder(TYPE_DELETE, uri); 187ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 188ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 189ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 19008b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * Create a {@link Builder} suitable for building a 19108b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * {@link ContentProviderOperation} to assert a set of values as provided 19208b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * through {@link Builder#withValues(ContentValues)}. 193ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 19408b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey public static Builder newAssertQuery(Uri uri) { 19508b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey return new Builder(TYPE_ASSERT, uri); 196ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 197ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 1988943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public Uri getUri() { 1998943737692169f564cd34a9c8d471f3a5d438712Fred Quintana return mUri; 2008943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 2018943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 20256f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana public boolean isYieldAllowed() { 20356f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana return mYieldAllowed; 20456f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana } 20556f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana 206bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey /** @hide exposed for unit tests */ 207bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey public int getType() { 208bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey return mType; 209bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey } 210bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey 2118943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public boolean isWriteOperation() { 2128943737692169f564cd34a9c8d471f3a5d438712Fred Quintana return mType == TYPE_DELETE || mType == TYPE_INSERT || mType == TYPE_UPDATE; 2138943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 2148943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 2158943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public boolean isReadOperation() { 21608b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey return mType == TYPE_ASSERT; 2178943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 2188943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 219ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 220ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Applies this operation using the given provider. The backRefs array is used to resolve any 221ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * back references that were requested using 222ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * {@link Builder#withValueBackReferences(ContentValues)} and 22303d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana * {@link Builder#withSelectionBackReference}. 224ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param provider the {@link ContentProvider} on which this batch is applied 225ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param backRefs a {@link ContentProviderResult} array that will be consulted 226ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * to resolve any requested back references. 227ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param numBackRefs the number of valid results on the backRefs array. 228ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return a {@link ContentProviderResult} that contains either the {@link Uri} of the inserted 229ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * row if this was an insert otherwise the number of rows affected. 230ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @throws OperationApplicationException thrown if either the insert fails or 231ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * if the number of rows affected didn't match the expected count 232ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 233ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public ContentProviderResult apply(ContentProvider provider, ContentProviderResult[] backRefs, 234ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana int numBackRefs) throws OperationApplicationException { 235ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana ContentValues values = resolveValueBackReferences(backRefs, numBackRefs); 236ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana String[] selectionArgs = 237ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana resolveSelectionArgsBackReferences(backRefs, numBackRefs); 238ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 239ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (mType == TYPE_INSERT) { 24003d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana Uri newUri = provider.insert(mUri, values); 241ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (newUri == null) { 242ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new OperationApplicationException("insert failed"); 243ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 244ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return new ContentProviderResult(newUri); 245ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 246ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 247ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana int numRows; 248ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (mType == TYPE_DELETE) { 249ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana numRows = provider.delete(mUri, mSelection, selectionArgs); 250ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } else if (mType == TYPE_UPDATE) { 25103d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana numRows = provider.update(mUri, values, mSelection, selectionArgs); 25208b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey } else if (mType == TYPE_ASSERT) { 25308b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey // Assert that all rows match expected values 2545ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana String[] projection = null; 2555ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana if (values != null) { 2565ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana // Build projection map from expected values 2575ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana final ArrayList<String> projectionList = new ArrayList<String>(); 2585ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana for (Map.Entry<String, Object> entry : values.valueSet()) { 2595ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana projectionList.add(entry.getKey()); 2605ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana } 2615ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana projection = projectionList.toArray(new String[projectionList.size()]); 2625ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana } 26308b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey final Cursor cursor = provider.query(mUri, projection, mSelection, selectionArgs, null); 264ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana try { 2655ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana numRows = cursor.getCount(); 2665ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana if (projection != null) { 2675ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana while (cursor.moveToNext()) { 2685ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana for (int i = 0; i < projection.length; i++) { 2695ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana final String cursorValue = cursor.getString(i); 2705ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana final String expectedValue = values.getAsString(projection[i]); 2715ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana if (!TextUtils.equals(cursorValue, expectedValue)) { 2725ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana // Throw exception when expected values don't match 27335abad216da8a49128c3899a206c15d44c471617Ken Shirriff Log.e(TAG, this.toString()); 2745ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana throw new OperationApplicationException("Found value " + cursorValue 2755ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana + " when expected " + expectedValue + " for column " 2765ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana + projection[i]); 2775ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana } 27808b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey } 27908b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey } 280ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 281ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } finally { 282ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana cursor.close(); 283ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 284ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } else { 28535abad216da8a49128c3899a206c15d44c471617Ken Shirriff Log.e(TAG, this.toString()); 286ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new IllegalStateException("bad type, " + mType); 287ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 288ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 289ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (mExpectedCount != null && mExpectedCount != numRows) { 29035abad216da8a49128c3899a206c15d44c471617Ken Shirriff Log.e(TAG, this.toString()); 291ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new OperationApplicationException("wrong number of rows: " + numRows); 292ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 293ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 294ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return new ContentProviderResult(numRows); 295ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 296ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 297ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 298ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * The ContentValues back references are represented as a ContentValues object where the 299ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * key refers to a column and the value is an index of the back reference whose 300ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * valued should be associated with the column. 301d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato * <p> 302d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato * This is intended to be a private method but it is exposed for 303d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato * unit testing purposes 304ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param backRefs an array of previous results 305ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param numBackRefs the number of valid previous results in backRefs 306ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return the ContentValues that should be used in this operation application after 307ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * expansion of back references. This can be called if either mValues or mValuesBackReferences 308ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * is null 309ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 310ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public ContentValues resolveValueBackReferences( 311ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana ContentProviderResult[] backRefs, int numBackRefs) { 312ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (mValuesBackReferences == null) { 313ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return mValues; 314ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 315ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana final ContentValues values; 316ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (mValues == null) { 317ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana values = new ContentValues(); 318ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } else { 319ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana values = new ContentValues(mValues); 320ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 321ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana for (Map.Entry<String, Object> entry : mValuesBackReferences.valueSet()) { 322ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana String key = entry.getKey(); 323ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana Integer backRefIndex = mValuesBackReferences.getAsInteger(key); 324ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (backRefIndex == null) { 32535abad216da8a49128c3899a206c15d44c471617Ken Shirriff Log.e(TAG, this.toString()); 326ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new IllegalArgumentException("values backref " + key + " is not an integer"); 327ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 328ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana values.put(key, backRefToValue(backRefs, numBackRefs, backRefIndex)); 329ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 330ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return values; 331ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 332ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 333ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 334ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * The Selection Arguments back references are represented as a Map of Integer->Integer where 335ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * the key is an index into the selection argument array (see {@link Builder#withSelection}) 336ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * and the value is the index of the previous result that should be used for that selection 337ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * argument array slot. 338d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato * <p> 339d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato * This is intended to be a private method but it is exposed for 340d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato * unit testing purposes 341ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param backRefs an array of previous results 342ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param numBackRefs the number of valid previous results in backRefs 343ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return the ContentValues that should be used in this operation application after 344ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * expansion of back references. This can be called if either mValues or mValuesBackReferences 345ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * is null 346ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 347ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public String[] resolveSelectionArgsBackReferences( 348ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana ContentProviderResult[] backRefs, int numBackRefs) { 349ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (mSelectionArgsBackReferences == null) { 350ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return mSelectionArgs; 351ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 352ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana String[] newArgs = new String[mSelectionArgs.length]; 353ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana System.arraycopy(mSelectionArgs, 0, newArgs, 0, mSelectionArgs.length); 354ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana for (Map.Entry<Integer, Integer> selectionArgBackRef 355ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana : mSelectionArgsBackReferences.entrySet()) { 356ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana final Integer selectionArgIndex = selectionArgBackRef.getKey(); 357ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana final int backRefIndex = selectionArgBackRef.getValue(); 3588851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana newArgs[selectionArgIndex] = 3598851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana String.valueOf(backRefToValue(backRefs, numBackRefs, backRefIndex)); 360ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 361ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return newArgs; 362ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 363ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 36435abad216da8a49128c3899a206c15d44c471617Ken Shirriff @Override 36535abad216da8a49128c3899a206c15d44c471617Ken Shirriff public String toString() { 36635abad216da8a49128c3899a206c15d44c471617Ken Shirriff return "mType: " + mType + ", mUri: " + mUri + 36735abad216da8a49128c3899a206c15d44c471617Ken Shirriff ", mSelection: " + mSelection + 36835abad216da8a49128c3899a206c15d44c471617Ken Shirriff ", mExpectedCount: " + mExpectedCount + 36935abad216da8a49128c3899a206c15d44c471617Ken Shirriff ", mYieldAllowed: " + mYieldAllowed + 37035abad216da8a49128c3899a206c15d44c471617Ken Shirriff ", mValues: " + mValues + 37135abad216da8a49128c3899a206c15d44c471617Ken Shirriff ", mValuesBackReferences: " + mValuesBackReferences + 37235abad216da8a49128c3899a206c15d44c471617Ken Shirriff ", mSelectionArgsBackReferences: " + mSelectionArgsBackReferences; 37335abad216da8a49128c3899a206c15d44c471617Ken Shirriff } 37435abad216da8a49128c3899a206c15d44c471617Ken Shirriff 375ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 376ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Return the string representation of the requested back reference. 377ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param backRefs an array of results 378ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param numBackRefs the number of items in the backRefs array that are valid 379ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param backRefIndex which backRef to be used 380ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @throws ArrayIndexOutOfBoundsException thrown if the backRefIndex is larger than 381ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * the numBackRefs 382ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return the string representation of the requested back reference. 383ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 38435abad216da8a49128c3899a206c15d44c471617Ken Shirriff private long backRefToValue(ContentProviderResult[] backRefs, int numBackRefs, 385ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana Integer backRefIndex) { 38603d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana if (backRefIndex >= numBackRefs) { 38735abad216da8a49128c3899a206c15d44c471617Ken Shirriff Log.e(TAG, this.toString()); 388ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new ArrayIndexOutOfBoundsException("asked for back ref " + backRefIndex 389ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana + " but there are only " + numBackRefs + " back refs"); 390ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 391ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana ContentProviderResult backRef = backRefs[backRefIndex]; 3928851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana long backRefValue; 393ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (backRef.uri != null) { 3948851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana backRefValue = ContentUris.parseId(backRef.uri); 395ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } else { 3968851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana backRefValue = backRef.count; 397ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 398ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return backRefValue; 399ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 400ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 4018943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public int describeContents() { 4028943737692169f564cd34a9c8d471f3a5d438712Fred Quintana return 0; 4038943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 4048943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 4058943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public static final Creator<ContentProviderOperation> CREATOR = 4068943737692169f564cd34a9c8d471f3a5d438712Fred Quintana new Creator<ContentProviderOperation>() { 4078943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public ContentProviderOperation createFromParcel(Parcel source) { 40803d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana return new ContentProviderOperation(source); 4098943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 4108943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 4118943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public ContentProviderOperation[] newArray(int size) { 4128943737692169f564cd34a9c8d471f3a5d438712Fred Quintana return new ContentProviderOperation[size]; 4138943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 4148943737692169f564cd34a9c8d471f3a5d438712Fred Quintana }; 4158943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 416ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 417ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Used to add parameters to a {@link ContentProviderOperation}. The {@link Builder} is 418ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * first created by calling {@link ContentProviderOperation#newInsert(android.net.Uri)}, 419ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * {@link ContentProviderOperation#newUpdate(android.net.Uri)}, 420ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * {@link ContentProviderOperation#newDelete(android.net.Uri)} or 42108b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * {@link ContentProviderOperation#newAssertQuery(Uri)}. The withXXX methods 422ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * can then be used to add parameters to the builder. See the specific methods to find for 423ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * which {@link Builder} type each is allowed. Call {@link #build} to create the 424ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * {@link ContentProviderOperation} once all the parameters have been supplied. 425ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 426ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public static class Builder { 427ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final int mType; 428ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final Uri mUri; 429ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private String mSelection; 430ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private String[] mSelectionArgs; 431ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private ContentValues mValues; 432ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private Integer mExpectedCount; 433ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private ContentValues mValuesBackReferences; 434ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private Map<Integer, Integer> mSelectionArgsBackReferences; 43556f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana private boolean mYieldAllowed; 436ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 437ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** Create a {@link Builder} of a given type. The uri must not be null. */ 438ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private Builder(int type, Uri uri) { 439ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (uri == null) { 440ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new IllegalArgumentException("uri must not be null"); 441ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 442ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mType = type; 443ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mUri = uri; 444ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 445ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 4468943737692169f564cd34a9c8d471f3a5d438712Fred Quintana /** Create a ContentProviderOperation from this {@link Builder}. */ 447ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public ContentProviderOperation build() { 4485ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana if (mType == TYPE_UPDATE) { 449c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana if ((mValues == null || mValues.size() == 0) 450c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana && (mValuesBackReferences == null || mValuesBackReferences.size() == 0)) { 451c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana throw new IllegalArgumentException("Empty values"); 452c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana } 453c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana } 4545ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana if (mType == TYPE_ASSERT) { 4555ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana if ((mValues == null || mValues.size() == 0) 4565ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana && (mValuesBackReferences == null || mValuesBackReferences.size() == 0) 4575ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana && (mExpectedCount == null)) { 4585ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana throw new IllegalArgumentException("Empty values"); 4595ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana } 4605ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana } 461ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return new ContentProviderOperation(this); 462ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 463ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 464ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 465ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Add a {@link ContentValues} of back references. The key is the name of the column 466ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * and the value is an integer that is the index of the previous result whose 467ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * value should be used for the column. The value is added as a {@link String}. 468ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * A column value from the back references takes precedence over a value specified in 469ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * {@link #withValues}. 47008b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * This can only be used with builders of type insert, update, or assert. 471ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return this builder, to allow for chaining. 472ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 473ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public Builder withValueBackReferences(ContentValues backReferences) { 47408b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) { 475ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new IllegalArgumentException( 47608b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey "only inserts, updates, and asserts can have value back-references"); 477ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 478ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mValuesBackReferences = backReferences; 479ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return this; 480ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 481ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 482ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 48303d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana * Add a ContentValues back reference. 48403d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana * A column value from the back references takes precedence over a value specified in 48503d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana * {@link #withValues}. 48608b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * This can only be used with builders of type insert, update, or assert. 487ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return this builder, to allow for chaining. 488ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 48903d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana public Builder withValueBackReference(String key, int previousResult) { 49008b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) { 491ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new IllegalArgumentException( 49208b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey "only inserts, updates, and asserts can have value back-references"); 493ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 49403d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana if (mValuesBackReferences == null) { 49503d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana mValuesBackReferences = new ContentValues(); 49603d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana } 49703d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana mValuesBackReferences.put(key, previousResult); 498ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return this; 499ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 500ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 501ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 50203d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana * Add a back references as a selection arg. Any value at that index of the selection arg 50303d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana * that was specified by {@link #withSelection} will be overwritten. 50408b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * This can only be used with builders of type update, delete, or assert. 505ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return this builder, to allow for chaining. 506ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 50703d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana public Builder withSelectionBackReference(int selectionArgIndex, int previousResult) { 50808b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey if (mType != TYPE_UPDATE && mType != TYPE_DELETE && mType != TYPE_ASSERT) { 50908b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey throw new IllegalArgumentException("only updates, deletes, and asserts " 51008b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey + "can have selection back-references"); 511ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 51203d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana if (mSelectionArgsBackReferences == null) { 51303d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana mSelectionArgsBackReferences = new HashMap<Integer, Integer>(); 51403d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana } 51503d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana mSelectionArgsBackReferences.put(selectionArgIndex, previousResult); 516ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return this; 517ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 518ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 519ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 5208943737692169f564cd34a9c8d471f3a5d438712Fred Quintana * The ContentValues to use. This may be null. These values may be overwritten by 521d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * the corresponding value specified by {@link #withValueBackReference} or by 522d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * future calls to {@link #withValues} or {@link #withValue}. 52308b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * This can only be used with builders of type insert, update, or assert. 5248943737692169f564cd34a9c8d471f3a5d438712Fred Quintana * @return this builder, to allow for chaining. 5258943737692169f564cd34a9c8d471f3a5d438712Fred Quintana */ 52603d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana public Builder withValues(ContentValues values) { 52708b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) { 52808b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey throw new IllegalArgumentException( 52908b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey "only inserts, updates, and asserts can have values"); 5308943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 531d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana if (mValues == null) { 532d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues = new ContentValues(); 533d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } 534d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.putAll(values); 5358943737692169f564cd34a9c8d471f3a5d438712Fred Quintana return this; 5368943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 5378943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 5388943737692169f564cd34a9c8d471f3a5d438712Fred Quintana /** 539d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * A value to insert or update. This value may be overwritten by 540d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * the corresponding value specified by {@link #withValueBackReference}. 54108b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * This can only be used with builders of type insert, update, or assert. 542d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * @param key the name of this value 543d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * @param value the value itself. the type must be acceptable for insertion by 544d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * {@link ContentValues#put} 545d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * @return this builder, to allow for chaining. 546d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana */ 547d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana public Builder withValue(String key, Object value) { 54808b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) { 549d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana throw new IllegalArgumentException("only inserts and updates can have values"); 550d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } 551d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana if (mValues == null) { 552d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues = new ContentValues(); 553d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } 554d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana if (value == null) { 555d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.putNull(key); 556d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof String) { 557d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (String) value); 558d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof Byte) { 559d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (Byte) value); 560d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof Short) { 561d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (Short) value); 562d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof Integer) { 563d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (Integer) value); 564d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof Long) { 565d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (Long) value); 566d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof Float) { 567d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (Float) value); 568d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof Double) { 569d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (Double) value); 570d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof Boolean) { 571d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (Boolean) value); 572d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof byte[]) { 573d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (byte[]) value); 574d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else { 575d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana throw new IllegalArgumentException("bad value type: " + value.getClass().getName()); 576d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } 577d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana return this; 578d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } 579bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey 580d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana /** 581ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * The selection and arguments to use. An occurrence of '?' in the selection will be 582ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * replaced with the corresponding occurence of the selection argument. Any of the 583ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * selection arguments may be overwritten by a selection argument back reference as 58403d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana * specified by {@link #withSelectionBackReference}. 58508b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * This can only be used with builders of type update, delete, or assert. 586ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return this builder, to allow for chaining. 587ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 588ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public Builder withSelection(String selection, String[] selectionArgs) { 58908b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey if (mType != TYPE_UPDATE && mType != TYPE_DELETE && mType != TYPE_ASSERT) { 590ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new IllegalArgumentException( 59108b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey "only updates, deletes, and asserts can have selections"); 592ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 593ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mSelection = selection; 594824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey if (selectionArgs == null) { 595824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey mSelectionArgs = null; 596824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey } else { 597824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey mSelectionArgs = new String[selectionArgs.length]; 598824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey System.arraycopy(selectionArgs, 0, mSelectionArgs, 0, selectionArgs.length); 599824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey } 600ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return this; 601ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 602ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 603ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 604ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * If set then if the number of rows affected by this operation do not match 605ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * this count {@link OperationApplicationException} will be throw. 60608b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * This can only be used with builders of type update, delete, or assert. 607ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return this builder, to allow for chaining. 608ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 609ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public Builder withExpectedCount(int count) { 61008b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey if (mType != TYPE_UPDATE && mType != TYPE_DELETE && mType != TYPE_ASSERT) { 611ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new IllegalArgumentException( 61208b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey "only updates, deletes, and asserts can have expected counts"); 613ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 614ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mExpectedCount = count; 615ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return this; 616ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 61756f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana 61856f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana public Builder withYieldAllowed(boolean yieldAllowed) { 61956f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana mYieldAllowed = yieldAllowed; 62056f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana return this; 62156f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana } 622ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 623ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana} 624