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 19ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintanaimport android.database.Cursor; 2008b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkeyimport android.net.Uri; 218943737692169f564cd34a9c8d471f3a5d438712Fred Quintanaimport android.os.Parcel; 2208b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkeyimport android.os.Parcelable; 2308b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkeyimport android.text.TextUtils; 2435abad216da8a49128c3899a206c15d44c471617Ken Shirriffimport android.util.Log; 25ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 2608b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkeyimport java.util.ArrayList; 278943737692169f564cd34a9c8d471f3a5d438712Fred Quintanaimport java.util.HashMap; 2808b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkeyimport java.util.Map; 29ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 308943737692169f564cd34a9c8d471f3a5d438712Fred Quintanapublic class ContentProviderOperation implements Parcelable { 31bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey /** @hide exposed for unit tests */ 32bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey public final static int TYPE_INSERT = 1; 33bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey /** @hide exposed for unit tests */ 34bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey public final static int TYPE_UPDATE = 2; 35bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey /** @hide exposed for unit tests */ 36bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey public final static int TYPE_DELETE = 3; 37bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey /** @hide exposed for unit tests */ 3808b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey public final static int TYPE_ASSERT = 4; 39ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 40ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final int mType; 41ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final Uri mUri; 42ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final String mSelection; 43ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final String[] mSelectionArgs; 44ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final ContentValues mValues; 45ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final Integer mExpectedCount; 46ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final ContentValues mValuesBackReferences; 47ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final Map<Integer, Integer> mSelectionArgsBackReferences; 4856f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana private final boolean mYieldAllowed; 49ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 5035abad216da8a49128c3899a206c15d44c471617Ken Shirriff private final static String TAG = "ContentProviderOperation"; 5135abad216da8a49128c3899a206c15d44c471617Ken Shirriff 52ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 53ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Creates a {@link ContentProviderOperation} by copying the contents of a 54ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * {@link Builder}. 55ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 56ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private ContentProviderOperation(Builder builder) { 57ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mType = builder.mType; 58ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mUri = builder.mUri; 59ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mValues = builder.mValues; 60ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mSelection = builder.mSelection; 61ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mSelectionArgs = builder.mSelectionArgs; 62ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mExpectedCount = builder.mExpectedCount; 63ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mSelectionArgsBackReferences = builder.mSelectionArgsBackReferences; 64ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mValuesBackReferences = builder.mValuesBackReferences; 6556f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana mYieldAllowed = builder.mYieldAllowed; 66ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 67ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 6803d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana private ContentProviderOperation(Parcel source) { 698943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mType = source.readInt(); 708943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mUri = Uri.CREATOR.createFromParcel(source); 718943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mValues = source.readInt() != 0 ? ContentValues.CREATOR.createFromParcel(source) : null; 728943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mSelection = source.readInt() != 0 ? source.readString() : null; 738943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mSelectionArgs = source.readInt() != 0 ? source.readStringArray() : null; 748943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mExpectedCount = source.readInt() != 0 ? source.readInt() : null; 758943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mValuesBackReferences = source.readInt() != 0 768943737692169f564cd34a9c8d471f3a5d438712Fred Quintana ? ContentValues.CREATOR.createFromParcel(source) 778943737692169f564cd34a9c8d471f3a5d438712Fred Quintana : null; 788943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mSelectionArgsBackReferences = source.readInt() != 0 798943737692169f564cd34a9c8d471f3a5d438712Fred Quintana ? new HashMap<Integer, Integer>() 808943737692169f564cd34a9c8d471f3a5d438712Fred Quintana : null; 818943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (mSelectionArgsBackReferences != null) { 828943737692169f564cd34a9c8d471f3a5d438712Fred Quintana final int count = source.readInt(); 838943737692169f564cd34a9c8d471f3a5d438712Fred Quintana for (int i = 0; i < count; i++) { 848943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mSelectionArgsBackReferences.put(source.readInt(), source.readInt()); 858943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 868943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 8756f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana mYieldAllowed = source.readInt() != 0; 888943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 898943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 908943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public void writeToParcel(Parcel dest, int flags) { 918943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(mType); 928943737692169f564cd34a9c8d471f3a5d438712Fred Quintana Uri.writeToParcel(dest, mUri); 938943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (mValues != null) { 948943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(1); 958943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mValues.writeToParcel(dest, 0); 968943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } else { 978943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(0); 988943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 998943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (mSelection != null) { 1008943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(1); 1018943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeString(mSelection); 1028943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } else { 1038943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(0); 1048943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1058943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (mSelectionArgs != null) { 1068943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(1); 1078943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeStringArray(mSelectionArgs); 1088943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } else { 1098943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(0); 1108943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1118943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (mExpectedCount != null) { 1128943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(1); 1138943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(mExpectedCount); 1148943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } else { 1158943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(0); 1168943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1178943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (mValuesBackReferences != null) { 1188943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(1); 1198943737692169f564cd34a9c8d471f3a5d438712Fred Quintana mValuesBackReferences.writeToParcel(dest, 0); 1208943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } else { 1218943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(0); 1228943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1238943737692169f564cd34a9c8d471f3a5d438712Fred Quintana if (mSelectionArgsBackReferences != null) { 1248943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(1); 1258943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(mSelectionArgsBackReferences.size()); 1268943737692169f564cd34a9c8d471f3a5d438712Fred Quintana for (Map.Entry<Integer, Integer> entry : mSelectionArgsBackReferences.entrySet()) { 1278943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(entry.getKey()); 1288943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(entry.getValue()); 1298943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1308943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } else { 1318943737692169f564cd34a9c8d471f3a5d438712Fred Quintana dest.writeInt(0); 1328943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 13356f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana dest.writeInt(mYieldAllowed ? 1 : 0); 1348943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1358943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 136ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 137ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Create a {@link Builder} suitable for building an insert {@link ContentProviderOperation}. 138ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param uri The {@link Uri} that is the target of the insert. 139ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return a {@link Builder} 140ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 141ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public static Builder newInsert(Uri uri) { 142ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return new Builder(TYPE_INSERT, uri); 143ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 144ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 145ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 146ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Create a {@link Builder} suitable for building an update {@link ContentProviderOperation}. 147ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param uri The {@link Uri} that is the target of the update. 148ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return a {@link Builder} 149ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 150ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public static Builder newUpdate(Uri uri) { 151ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return new Builder(TYPE_UPDATE, uri); 152ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 153ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 154ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 155ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Create a {@link Builder} suitable for building a delete {@link ContentProviderOperation}. 156ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param uri The {@link Uri} that is the target of the delete. 157ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return a {@link Builder} 158ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 159ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public static Builder newDelete(Uri uri) { 160ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return new Builder(TYPE_DELETE, uri); 161ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 162ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 163ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 16408b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * Create a {@link Builder} suitable for building a 16508b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * {@link ContentProviderOperation} to assert a set of values as provided 16608b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * through {@link Builder#withValues(ContentValues)}. 167ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 16808b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey public static Builder newAssertQuery(Uri uri) { 16908b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey return new Builder(TYPE_ASSERT, uri); 170ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 171ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 1728943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public Uri getUri() { 1738943737692169f564cd34a9c8d471f3a5d438712Fred Quintana return mUri; 1748943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1758943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 17656f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana public boolean isYieldAllowed() { 17756f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana return mYieldAllowed; 17856f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana } 17956f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana 180bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey /** @hide exposed for unit tests */ 181bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey public int getType() { 182bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey return mType; 183bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey } 184bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey 1858943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public boolean isWriteOperation() { 1868943737692169f564cd34a9c8d471f3a5d438712Fred Quintana return mType == TYPE_DELETE || mType == TYPE_INSERT || mType == TYPE_UPDATE; 1878943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1888943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 1898943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public boolean isReadOperation() { 19008b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey return mType == TYPE_ASSERT; 1918943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 1928943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 193ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 194ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Applies this operation using the given provider. The backRefs array is used to resolve any 195ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * back references that were requested using 196ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * {@link Builder#withValueBackReferences(ContentValues)} and 19703d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana * {@link Builder#withSelectionBackReference}. 198ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param provider the {@link ContentProvider} on which this batch is applied 199ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param backRefs a {@link ContentProviderResult} array that will be consulted 200ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * to resolve any requested back references. 201ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param numBackRefs the number of valid results on the backRefs array. 202ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return a {@link ContentProviderResult} that contains either the {@link Uri} of the inserted 203ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * row if this was an insert otherwise the number of rows affected. 204ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @throws OperationApplicationException thrown if either the insert fails or 205ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * if the number of rows affected didn't match the expected count 206ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 207ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public ContentProviderResult apply(ContentProvider provider, ContentProviderResult[] backRefs, 208ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana int numBackRefs) throws OperationApplicationException { 209ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana ContentValues values = resolveValueBackReferences(backRefs, numBackRefs); 210ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana String[] selectionArgs = 211ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana resolveSelectionArgsBackReferences(backRefs, numBackRefs); 212ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 213ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (mType == TYPE_INSERT) { 21403d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana Uri newUri = provider.insert(mUri, values); 215ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (newUri == null) { 216ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new OperationApplicationException("insert failed"); 217ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 218ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return new ContentProviderResult(newUri); 219ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 220ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 221ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana int numRows; 222ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (mType == TYPE_DELETE) { 223ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana numRows = provider.delete(mUri, mSelection, selectionArgs); 224ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } else if (mType == TYPE_UPDATE) { 22503d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana numRows = provider.update(mUri, values, mSelection, selectionArgs); 22608b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey } else if (mType == TYPE_ASSERT) { 22708b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey // Assert that all rows match expected values 2285ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana String[] projection = null; 2295ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana if (values != null) { 2305ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana // Build projection map from expected values 2315ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana final ArrayList<String> projectionList = new ArrayList<String>(); 2325ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana for (Map.Entry<String, Object> entry : values.valueSet()) { 2335ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana projectionList.add(entry.getKey()); 2345ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana } 2355ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana projection = projectionList.toArray(new String[projectionList.size()]); 2365ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana } 23708b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey final Cursor cursor = provider.query(mUri, projection, mSelection, selectionArgs, null); 238ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana try { 2395ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana numRows = cursor.getCount(); 2405ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana if (projection != null) { 2415ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana while (cursor.moveToNext()) { 2425ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana for (int i = 0; i < projection.length; i++) { 2435ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana final String cursorValue = cursor.getString(i); 2445ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana final String expectedValue = values.getAsString(projection[i]); 2455ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana if (!TextUtils.equals(cursorValue, expectedValue)) { 2465ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana // Throw exception when expected values don't match 24735abad216da8a49128c3899a206c15d44c471617Ken Shirriff Log.e(TAG, this.toString()); 2485ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana throw new OperationApplicationException("Found value " + cursorValue 2495ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana + " when expected " + expectedValue + " for column " 2505ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana + projection[i]); 2515ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana } 25208b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey } 25308b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey } 254ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 255ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } finally { 256ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana cursor.close(); 257ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 258ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } else { 25935abad216da8a49128c3899a206c15d44c471617Ken Shirriff Log.e(TAG, this.toString()); 260ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new IllegalStateException("bad type, " + mType); 261ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 262ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 263ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (mExpectedCount != null && mExpectedCount != numRows) { 26435abad216da8a49128c3899a206c15d44c471617Ken Shirriff Log.e(TAG, this.toString()); 265ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new OperationApplicationException("wrong number of rows: " + numRows); 266ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 267ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 268ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return new ContentProviderResult(numRows); 269ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 270ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 271ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 272ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * The ContentValues back references are represented as a ContentValues object where the 273ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * key refers to a column and the value is an index of the back reference whose 274ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * valued should be associated with the column. 275d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato * <p> 276d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato * This is intended to be a private method but it is exposed for 277d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato * unit testing purposes 278ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param backRefs an array of previous results 279ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param numBackRefs the number of valid previous results in backRefs 280ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return the ContentValues that should be used in this operation application after 281ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * expansion of back references. This can be called if either mValues or mValuesBackReferences 282ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * is null 283ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 284ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public ContentValues resolveValueBackReferences( 285ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana ContentProviderResult[] backRefs, int numBackRefs) { 286ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (mValuesBackReferences == null) { 287ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return mValues; 288ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 289ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana final ContentValues values; 290ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (mValues == null) { 291ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana values = new ContentValues(); 292ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } else { 293ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana values = new ContentValues(mValues); 294ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 295ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana for (Map.Entry<String, Object> entry : mValuesBackReferences.valueSet()) { 296ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana String key = entry.getKey(); 297ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana Integer backRefIndex = mValuesBackReferences.getAsInteger(key); 298ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (backRefIndex == null) { 29935abad216da8a49128c3899a206c15d44c471617Ken Shirriff Log.e(TAG, this.toString()); 300ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new IllegalArgumentException("values backref " + key + " is not an integer"); 301ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 302ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana values.put(key, backRefToValue(backRefs, numBackRefs, backRefIndex)); 303ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 304ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return values; 305ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 306ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 307ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 308ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * The Selection Arguments back references are represented as a Map of Integer->Integer where 309ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * the key is an index into the selection argument array (see {@link Builder#withSelection}) 310ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * and the value is the index of the previous result that should be used for that selection 311ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * argument array slot. 312d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato * <p> 313d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato * This is intended to be a private method but it is exposed for 314d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato * unit testing purposes 315ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param backRefs an array of previous results 316ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param numBackRefs the number of valid previous results in backRefs 317ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return the ContentValues that should be used in this operation application after 318ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * expansion of back references. This can be called if either mValues or mValuesBackReferences 319ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * is null 320ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 321ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public String[] resolveSelectionArgsBackReferences( 322ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana ContentProviderResult[] backRefs, int numBackRefs) { 323ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (mSelectionArgsBackReferences == null) { 324ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return mSelectionArgs; 325ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 326ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana String[] newArgs = new String[mSelectionArgs.length]; 327ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana System.arraycopy(mSelectionArgs, 0, newArgs, 0, mSelectionArgs.length); 328ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana for (Map.Entry<Integer, Integer> selectionArgBackRef 329ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana : mSelectionArgsBackReferences.entrySet()) { 330ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana final Integer selectionArgIndex = selectionArgBackRef.getKey(); 331ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana final int backRefIndex = selectionArgBackRef.getValue(); 3328851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana newArgs[selectionArgIndex] = 3338851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana String.valueOf(backRefToValue(backRefs, numBackRefs, backRefIndex)); 334ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 335ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return newArgs; 336ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 337ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 33835abad216da8a49128c3899a206c15d44c471617Ken Shirriff @Override 33935abad216da8a49128c3899a206c15d44c471617Ken Shirriff public String toString() { 34035abad216da8a49128c3899a206c15d44c471617Ken Shirriff return "mType: " + mType + ", mUri: " + mUri + 34135abad216da8a49128c3899a206c15d44c471617Ken Shirriff ", mSelection: " + mSelection + 34235abad216da8a49128c3899a206c15d44c471617Ken Shirriff ", mExpectedCount: " + mExpectedCount + 34335abad216da8a49128c3899a206c15d44c471617Ken Shirriff ", mYieldAllowed: " + mYieldAllowed + 34435abad216da8a49128c3899a206c15d44c471617Ken Shirriff ", mValues: " + mValues + 34535abad216da8a49128c3899a206c15d44c471617Ken Shirriff ", mValuesBackReferences: " + mValuesBackReferences + 34635abad216da8a49128c3899a206c15d44c471617Ken Shirriff ", mSelectionArgsBackReferences: " + mSelectionArgsBackReferences; 34735abad216da8a49128c3899a206c15d44c471617Ken Shirriff } 34835abad216da8a49128c3899a206c15d44c471617Ken Shirriff 349ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 350ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Return the string representation of the requested back reference. 351ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param backRefs an array of results 352ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param numBackRefs the number of items in the backRefs array that are valid 353ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @param backRefIndex which backRef to be used 354ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @throws ArrayIndexOutOfBoundsException thrown if the backRefIndex is larger than 355ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * the numBackRefs 356ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return the string representation of the requested back reference. 357ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 35835abad216da8a49128c3899a206c15d44c471617Ken Shirriff private long backRefToValue(ContentProviderResult[] backRefs, int numBackRefs, 359ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana Integer backRefIndex) { 36003d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana if (backRefIndex >= numBackRefs) { 36135abad216da8a49128c3899a206c15d44c471617Ken Shirriff Log.e(TAG, this.toString()); 362ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new ArrayIndexOutOfBoundsException("asked for back ref " + backRefIndex 363ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana + " but there are only " + numBackRefs + " back refs"); 364ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 365ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana ContentProviderResult backRef = backRefs[backRefIndex]; 3668851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana long backRefValue; 367ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (backRef.uri != null) { 3688851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana backRefValue = ContentUris.parseId(backRef.uri); 369ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } else { 3708851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana backRefValue = backRef.count; 371ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 372ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return backRefValue; 373ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 374ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 3758943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public int describeContents() { 3768943737692169f564cd34a9c8d471f3a5d438712Fred Quintana return 0; 3778943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 3788943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 3798943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public static final Creator<ContentProviderOperation> CREATOR = 3808943737692169f564cd34a9c8d471f3a5d438712Fred Quintana new Creator<ContentProviderOperation>() { 3818943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public ContentProviderOperation createFromParcel(Parcel source) { 38203d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana return new ContentProviderOperation(source); 3838943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 3848943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 3858943737692169f564cd34a9c8d471f3a5d438712Fred Quintana public ContentProviderOperation[] newArray(int size) { 3868943737692169f564cd34a9c8d471f3a5d438712Fred Quintana return new ContentProviderOperation[size]; 3878943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 3888943737692169f564cd34a9c8d471f3a5d438712Fred Quintana }; 3898943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 3908943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 391ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 392ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Used to add parameters to a {@link ContentProviderOperation}. The {@link Builder} is 393ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * first created by calling {@link ContentProviderOperation#newInsert(android.net.Uri)}, 394ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * {@link ContentProviderOperation#newUpdate(android.net.Uri)}, 395ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * {@link ContentProviderOperation#newDelete(android.net.Uri)} or 39608b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * {@link ContentProviderOperation#newAssertQuery(Uri)}. The withXXX methods 397ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * can then be used to add parameters to the builder. See the specific methods to find for 398ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * which {@link Builder} type each is allowed. Call {@link #build} to create the 399ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * {@link ContentProviderOperation} once all the parameters have been supplied. 400ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 401ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public static class Builder { 402ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final int mType; 403ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private final Uri mUri; 404ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private String mSelection; 405ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private String[] mSelectionArgs; 406ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private ContentValues mValues; 407ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private Integer mExpectedCount; 408ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private ContentValues mValuesBackReferences; 409ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private Map<Integer, Integer> mSelectionArgsBackReferences; 41056f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana private boolean mYieldAllowed; 411ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 412ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** Create a {@link Builder} of a given type. The uri must not be null. */ 413ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana private Builder(int type, Uri uri) { 414ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana if (uri == null) { 415ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new IllegalArgumentException("uri must not be null"); 416ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 417ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mType = type; 418ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mUri = uri; 419ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 420ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 4218943737692169f564cd34a9c8d471f3a5d438712Fred Quintana /** Create a ContentProviderOperation from this {@link Builder}. */ 422ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public ContentProviderOperation build() { 4235ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana if (mType == TYPE_UPDATE) { 424c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana if ((mValues == null || mValues.size() == 0) 425c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana && (mValuesBackReferences == null || mValuesBackReferences.size() == 0)) { 426c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana throw new IllegalArgumentException("Empty values"); 427c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana } 428c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana } 4295ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana if (mType == TYPE_ASSERT) { 4305ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana if ((mValues == null || mValues.size() == 0) 4315ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana && (mValuesBackReferences == null || mValuesBackReferences.size() == 0) 4325ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana && (mExpectedCount == null)) { 4335ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana throw new IllegalArgumentException("Empty values"); 4345ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana } 4355ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana } 436ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return new ContentProviderOperation(this); 437ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 438ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 439ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 440ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * Add a {@link ContentValues} of back references. The key is the name of the column 441ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * and the value is an integer that is the index of the previous result whose 442ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * value should be used for the column. The value is added as a {@link String}. 443ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * A column value from the back references takes precedence over a value specified in 444ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * {@link #withValues}. 44508b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * This can only be used with builders of type insert, update, or assert. 446ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return this builder, to allow for chaining. 447ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 448ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public Builder withValueBackReferences(ContentValues backReferences) { 44908b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) { 450ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new IllegalArgumentException( 45108b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey "only inserts, updates, and asserts can have value back-references"); 452ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 453ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mValuesBackReferences = backReferences; 454ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return this; 455ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 456ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 457ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 45803d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana * Add a ContentValues back reference. 45903d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana * A column value from the back references takes precedence over a value specified in 46003d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana * {@link #withValues}. 46108b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * This can only be used with builders of type insert, update, or assert. 462ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return this builder, to allow for chaining. 463ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 46403d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana public Builder withValueBackReference(String key, int previousResult) { 46508b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) { 466ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new IllegalArgumentException( 46708b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey "only inserts, updates, and asserts can have value back-references"); 468ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 46903d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana if (mValuesBackReferences == null) { 47003d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana mValuesBackReferences = new ContentValues(); 47103d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana } 47203d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana mValuesBackReferences.put(key, previousResult); 473ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return this; 474ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 475ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 476ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 47703d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana * Add a back references as a selection arg. Any value at that index of the selection arg 47803d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana * that was specified by {@link #withSelection} will be overwritten. 47908b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * This can only be used with builders of type update, delete, or assert. 480ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return this builder, to allow for chaining. 481ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 48203d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana public Builder withSelectionBackReference(int selectionArgIndex, int previousResult) { 48308b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey if (mType != TYPE_UPDATE && mType != TYPE_DELETE && mType != TYPE_ASSERT) { 48408b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey throw new IllegalArgumentException("only updates, deletes, and asserts " 48508b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey + "can have selection back-references"); 486ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 48703d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana if (mSelectionArgsBackReferences == null) { 48803d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana mSelectionArgsBackReferences = new HashMap<Integer, Integer>(); 48903d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana } 49003d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana mSelectionArgsBackReferences.put(selectionArgIndex, previousResult); 491ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return this; 492ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 493ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 494ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 4958943737692169f564cd34a9c8d471f3a5d438712Fred Quintana * The ContentValues to use. This may be null. These values may be overwritten by 496d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * the corresponding value specified by {@link #withValueBackReference} or by 497d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * future calls to {@link #withValues} or {@link #withValue}. 49808b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * This can only be used with builders of type insert, update, or assert. 4998943737692169f564cd34a9c8d471f3a5d438712Fred Quintana * @return this builder, to allow for chaining. 5008943737692169f564cd34a9c8d471f3a5d438712Fred Quintana */ 50103d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana public Builder withValues(ContentValues values) { 50208b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) { 50308b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey throw new IllegalArgumentException( 50408b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey "only inserts, updates, and asserts can have values"); 5058943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 506d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana if (mValues == null) { 507d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues = new ContentValues(); 508d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } 509d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.putAll(values); 5108943737692169f564cd34a9c8d471f3a5d438712Fred Quintana return this; 5118943737692169f564cd34a9c8d471f3a5d438712Fred Quintana } 5128943737692169f564cd34a9c8d471f3a5d438712Fred Quintana 5138943737692169f564cd34a9c8d471f3a5d438712Fred Quintana /** 514d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * A value to insert or update. This value may be overwritten by 515d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * the corresponding value specified by {@link #withValueBackReference}. 51608b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * This can only be used with builders of type insert, update, or assert. 517d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * @param key the name of this value 518d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * @param value the value itself. the type must be acceptable for insertion by 519d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * {@link ContentValues#put} 520d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana * @return this builder, to allow for chaining. 521d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana */ 522d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana public Builder withValue(String key, Object value) { 52308b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) { 524d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana throw new IllegalArgumentException("only inserts and updates can have values"); 525d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } 526d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana if (mValues == null) { 527d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues = new ContentValues(); 528d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } 529d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana if (value == null) { 530d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.putNull(key); 531d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof String) { 532d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (String) value); 533d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof Byte) { 534d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (Byte) value); 535d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof Short) { 536d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (Short) value); 537d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof Integer) { 538d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (Integer) value); 539d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof Long) { 540d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (Long) value); 541d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof Float) { 542d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (Float) value); 543d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof Double) { 544d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (Double) value); 545d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof Boolean) { 546d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (Boolean) value); 547d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else if (value instanceof byte[]) { 548d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana mValues.put(key, (byte[]) value); 549d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } else { 550d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana throw new IllegalArgumentException("bad value type: " + value.getClass().getName()); 551d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } 552d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana return this; 553d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana } 554bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey 555d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana /** 556ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * The selection and arguments to use. An occurrence of '?' in the selection will be 557ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * replaced with the corresponding occurence of the selection argument. Any of the 558ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * selection arguments may be overwritten by a selection argument back reference as 55903d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana * specified by {@link #withSelectionBackReference}. 56008b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * This can only be used with builders of type update, delete, or assert. 561ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return this builder, to allow for chaining. 562ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 563ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public Builder withSelection(String selection, String[] selectionArgs) { 56408b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey if (mType != TYPE_UPDATE && mType != TYPE_DELETE && mType != TYPE_ASSERT) { 565ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new IllegalArgumentException( 56608b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey "only updates, deletes, and asserts can have selections"); 567ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 568ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mSelection = selection; 569824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey if (selectionArgs == null) { 570824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey mSelectionArgs = null; 571824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey } else { 572824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey mSelectionArgs = new String[selectionArgs.length]; 573824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey System.arraycopy(selectionArgs, 0, mSelectionArgs, 0, selectionArgs.length); 574824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey } 575ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return this; 576ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 577ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana 578ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana /** 579ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * If set then if the number of rows affected by this operation do not match 580ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * this count {@link OperationApplicationException} will be throw. 58108b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey * This can only be used with builders of type update, delete, or assert. 582ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana * @return this builder, to allow for chaining. 583ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana */ 584ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana public Builder withExpectedCount(int count) { 58508b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey if (mType != TYPE_UPDATE && mType != TYPE_DELETE && mType != TYPE_ASSERT) { 586ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana throw new IllegalArgumentException( 58708b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey "only updates, deletes, and asserts can have expected counts"); 588ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 589ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana mExpectedCount = count; 590ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana return this; 591ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 59256f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana 59356f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana public Builder withYieldAllowed(boolean yieldAllowed) { 59456f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana mYieldAllowed = yieldAllowed; 59556f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana return this; 59656f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana } 597ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana } 598ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana} 599