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
31764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown/**
32764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown * Represents a single operation to be performed as part of a batch of operations.
33764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown *
34764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown * @see ContentProvider#applyBatch(ArrayList)
35764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown */
368943737692169f564cd34a9c8d471f3a5d438712Fred Quintanapublic class ContentProviderOperation implements Parcelable {
37bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey    /** @hide exposed for unit tests */
38bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey    public final static int TYPE_INSERT = 1;
39bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey    /** @hide exposed for unit tests */
40bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey    public final static int TYPE_UPDATE = 2;
41bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey    /** @hide exposed for unit tests */
42bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey    public final static int TYPE_DELETE = 3;
43bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey    /** @hide exposed for unit tests */
4408b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey    public final static int TYPE_ASSERT = 4;
45ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
46ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    private final int mType;
47ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    private final Uri mUri;
48ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    private final String mSelection;
49ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    private final String[] mSelectionArgs;
50ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    private final ContentValues mValues;
51ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    private final Integer mExpectedCount;
52ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    private final ContentValues mValuesBackReferences;
53ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    private final Map<Integer, Integer> mSelectionArgsBackReferences;
5456f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana    private final boolean mYieldAllowed;
55ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
5635abad216da8a49128c3899a206c15d44c471617Ken Shirriff    private final static String TAG = "ContentProviderOperation";
5735abad216da8a49128c3899a206c15d44c471617Ken Shirriff
58ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    /**
59ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * Creates a {@link ContentProviderOperation} by copying the contents of a
60ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * {@link Builder}.
61ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     */
62ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    private ContentProviderOperation(Builder builder) {
63ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        mType = builder.mType;
64ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        mUri = builder.mUri;
65ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        mValues = builder.mValues;
66ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        mSelection = builder.mSelection;
67ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        mSelectionArgs = builder.mSelectionArgs;
68ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        mExpectedCount = builder.mExpectedCount;
69ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        mSelectionArgsBackReferences = builder.mSelectionArgsBackReferences;
70ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        mValuesBackReferences = builder.mValuesBackReferences;
7156f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana        mYieldAllowed = builder.mYieldAllowed;
72ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    }
73ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
7403d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana    private ContentProviderOperation(Parcel source) {
758943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        mType = source.readInt();
768943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        mUri = Uri.CREATOR.createFromParcel(source);
778943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        mValues = source.readInt() != 0 ? ContentValues.CREATOR.createFromParcel(source) : null;
788943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        mSelection = source.readInt() != 0 ? source.readString() : null;
798943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        mSelectionArgs = source.readInt() != 0 ? source.readStringArray() : null;
808943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        mExpectedCount = source.readInt() != 0 ? source.readInt() : null;
818943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        mValuesBackReferences = source.readInt() != 0
828943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                ? ContentValues.CREATOR.createFromParcel(source)
838943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                : null;
848943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        mSelectionArgsBackReferences = source.readInt() != 0
858943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                ? new HashMap<Integer, Integer>()
868943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                : null;
878943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        if (mSelectionArgsBackReferences != null) {
888943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            final int count = source.readInt();
898943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            for (int i = 0; i < count; i++) {
908943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                mSelectionArgsBackReferences.put(source.readInt(), source.readInt());
918943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            }
928943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        }
9356f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana        mYieldAllowed = source.readInt() != 0;
948943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    }
958943737692169f564cd34a9c8d471f3a5d438712Fred Quintana
96d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot    /** @hide */
97d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot    public ContentProviderOperation(ContentProviderOperation cpo, boolean removeUserIdFromUri) {
98d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        mType = cpo.mType;
99d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        if (removeUserIdFromUri) {
100d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot            mUri = ContentProvider.getUriWithoutUserId(cpo.mUri);
101d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        } else {
102d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot            mUri = cpo.mUri;
103d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        }
104d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        mValues = cpo.mValues;
105d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        mSelection = cpo.mSelection;
106d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        mSelectionArgs = cpo.mSelectionArgs;
107d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        mExpectedCount = cpo.mExpectedCount;
108d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        mSelectionArgsBackReferences = cpo.mSelectionArgsBackReferences;
109d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        mValuesBackReferences = cpo.mValuesBackReferences;
110d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        mYieldAllowed = cpo.mYieldAllowed;
111d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot    }
112d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot
113d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot    /** @hide */
114d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot    public ContentProviderOperation getWithoutUserIdInUri() {
115d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        if (ContentProvider.uriHasUserId(mUri)) {
116d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot            return new ContentProviderOperation(this, true);
117d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        }
118d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot        return this;
119d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot    }
120d85fc72fb810858f7502e7e7f1bad53e1bf03eddNicolas Prevot
1218943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    public void writeToParcel(Parcel dest, int flags) {
1228943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        dest.writeInt(mType);
1238943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        Uri.writeToParcel(dest, mUri);
1248943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        if (mValues != null) {
1258943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeInt(1);
1268943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            mValues.writeToParcel(dest, 0);
1278943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        } else {
1288943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeInt(0);
1298943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        }
1308943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        if (mSelection != null) {
1318943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeInt(1);
1328943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeString(mSelection);
1338943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        } else {
1348943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeInt(0);
1358943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        }
1368943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        if (mSelectionArgs != null) {
1378943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeInt(1);
1388943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeStringArray(mSelectionArgs);
1398943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        } else {
1408943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeInt(0);
1418943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        }
1428943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        if (mExpectedCount != null) {
1438943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeInt(1);
1448943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeInt(mExpectedCount);
1458943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        } else {
1468943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeInt(0);
1478943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        }
1488943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        if (mValuesBackReferences != null) {
1498943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeInt(1);
1508943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            mValuesBackReferences.writeToParcel(dest, 0);
1518943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        } else {
1528943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeInt(0);
1538943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        }
1548943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        if (mSelectionArgsBackReferences != null) {
1558943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeInt(1);
1568943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeInt(mSelectionArgsBackReferences.size());
1578943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            for (Map.Entry<Integer, Integer> entry : mSelectionArgsBackReferences.entrySet()) {
1588943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                dest.writeInt(entry.getKey());
1598943737692169f564cd34a9c8d471f3a5d438712Fred Quintana                dest.writeInt(entry.getValue());
1608943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            }
1618943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        } else {
1628943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            dest.writeInt(0);
1638943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        }
16456f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana        dest.writeInt(mYieldAllowed ? 1 : 0);
1658943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    }
1668943737692169f564cd34a9c8d471f3a5d438712Fred Quintana
167ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    /**
168ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * Create a {@link Builder} suitable for building an insert {@link ContentProviderOperation}.
169ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param uri The {@link Uri} that is the target of the insert.
170ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @return a {@link Builder}
171ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     */
172ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    public static Builder newInsert(Uri uri) {
173ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        return new Builder(TYPE_INSERT, uri);
174ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    }
175ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
176ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    /**
177ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * Create a {@link Builder} suitable for building an update {@link ContentProviderOperation}.
178ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param uri The {@link Uri} that is the target of the update.
179ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @return a {@link Builder}
180ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     */
181ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    public static Builder newUpdate(Uri uri) {
182ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        return new Builder(TYPE_UPDATE, uri);
183ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    }
184ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
185ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    /**
186ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * Create a {@link Builder} suitable for building a delete {@link ContentProviderOperation}.
187ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param uri The {@link Uri} that is the target of the delete.
188ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @return a {@link Builder}
189ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     */
190ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    public static Builder newDelete(Uri uri) {
191ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        return new Builder(TYPE_DELETE, uri);
192ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    }
193ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
194ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    /**
19508b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey     * Create a {@link Builder} suitable for building a
19608b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey     * {@link ContentProviderOperation} to assert a set of values as provided
19708b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey     * through {@link Builder#withValues(ContentValues)}.
198ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     */
19908b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey    public static Builder newAssertQuery(Uri uri) {
20008b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey        return new Builder(TYPE_ASSERT, uri);
201ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    }
202ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
203764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown    /**
204764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * Gets the Uri for the target of the operation.
205764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     */
2068943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    public Uri getUri() {
2078943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        return mUri;
2088943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    }
2098943737692169f564cd34a9c8d471f3a5d438712Fred Quintana
210764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown    /**
211764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * Returns true if the operation allows yielding the database to other transactions
212764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * if the database is contended.
213764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     *
214764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * @see android.database.sqlite.SQLiteDatabase#yieldIfContendedSafely()
215764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     */
21656f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana    public boolean isYieldAllowed() {
21756f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana        return mYieldAllowed;
21856f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana    }
21956f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana
220bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey    /** @hide exposed for unit tests */
221bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey    public int getType() {
222bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey        return mType;
223bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey    }
224bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey
225764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown    /**
226764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * Returns true if the operation represents an insertion.
227764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     *
228764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * @see #newInsert
229764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     */
2301cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell    public boolean isInsert() {
2311cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell        return mType == TYPE_INSERT;
2321cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell    }
2331cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell
234764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown    /**
235764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * Returns true if the operation represents a deletion.
236764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     *
237764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * @see #newDelete
238764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     */
2391cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell    public boolean isDelete() {
2401cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell        return mType == TYPE_DELETE;
2411cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell    }
2421cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell
243764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown    /**
244764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * Returns true if the operation represents an update.
245764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     *
246764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * @see #newUpdate
247764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     */
2481cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell    public boolean isUpdate() {
2491cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell        return mType == TYPE_UPDATE;
2501cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell    }
2511cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell
252764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown    /**
253764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * Returns true if the operation represents an assert query.
254764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     *
255764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * @see #newAssertQuery
256764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     */
2571cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell    public boolean isAssertQuery() {
2581cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell        return mType == TYPE_ASSERT;
2591cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell    }
2601cf7405f1f4cdf823f9ff8378185af015653772aBrian Attwell
261764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown    /**
262764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * Returns true if the operation represents an insertion, deletion, or update.
263764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     *
264764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * @see #isInsert
265764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * @see #isDelete
266764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * @see #isUpdate
267764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     */
2688943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    public boolean isWriteOperation() {
2698943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        return mType == TYPE_DELETE || mType == TYPE_INSERT || mType == TYPE_UPDATE;
2708943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    }
2718943737692169f564cd34a9c8d471f3a5d438712Fred Quintana
272764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown    /**
273764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * Returns true if the operation represents an assert query.
274764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     *
275764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     * @see #isAssertQuery
276764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown     */
2778943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    public boolean isReadOperation() {
27808b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey        return mType == TYPE_ASSERT;
2798943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    }
2808943737692169f564cd34a9c8d471f3a5d438712Fred Quintana
281ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    /**
282ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * Applies this operation using the given provider. The backRefs array is used to resolve any
283ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * back references that were requested using
284ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * {@link Builder#withValueBackReferences(ContentValues)} and
28503d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana     * {@link Builder#withSelectionBackReference}.
286ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param provider the {@link ContentProvider} on which this batch is applied
287ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param backRefs a {@link ContentProviderResult} array that will be consulted
288ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * to resolve any requested back references.
289ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param numBackRefs the number of valid results on the backRefs array.
290ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @return a {@link ContentProviderResult} that contains either the {@link Uri} of the inserted
291ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * row if this was an insert otherwise the number of rows affected.
292ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @throws OperationApplicationException thrown if either the insert fails or
293ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * if the number of rows affected didn't match the expected count
294ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     */
295ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    public ContentProviderResult apply(ContentProvider provider, ContentProviderResult[] backRefs,
296ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            int numBackRefs) throws OperationApplicationException {
297ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        ContentValues values = resolveValueBackReferences(backRefs, numBackRefs);
298ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        String[] selectionArgs =
299ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana                resolveSelectionArgsBackReferences(backRefs, numBackRefs);
300ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
301ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        if (mType == TYPE_INSERT) {
30203d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana            Uri newUri = provider.insert(mUri, values);
303ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            if (newUri == null) {
304ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana                throw new OperationApplicationException("insert failed");
305ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            }
306ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            return new ContentProviderResult(newUri);
307ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
308ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
309ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        int numRows;
310ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        if (mType == TYPE_DELETE) {
311ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            numRows = provider.delete(mUri, mSelection, selectionArgs);
312ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        } else if (mType == TYPE_UPDATE) {
31303d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana            numRows = provider.update(mUri, values, mSelection, selectionArgs);
31408b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey        } else if (mType == TYPE_ASSERT) {
31508b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey            // Assert that all rows match expected values
3165ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana            String[] projection =  null;
3175ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana            if (values != null) {
3185ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                // Build projection map from expected values
3195ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                final ArrayList<String> projectionList = new ArrayList<String>();
3205ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                for (Map.Entry<String, Object> entry : values.valueSet()) {
3215ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                    projectionList.add(entry.getKey());
3225ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                }
3235ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                projection = projectionList.toArray(new String[projectionList.size()]);
3245ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana            }
32508b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey            final Cursor cursor = provider.query(mUri, projection, mSelection, selectionArgs, null);
326ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            try {
3275ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                numRows = cursor.getCount();
3285ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                if (projection != null) {
3295ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                    while (cursor.moveToNext()) {
3305ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                        for (int i = 0; i < projection.length; i++) {
3315ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                            final String cursorValue = cursor.getString(i);
3325ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                            final String expectedValue = values.getAsString(projection[i]);
3335ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                            if (!TextUtils.equals(cursorValue, expectedValue)) {
3345ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                                // Throw exception when expected values don't match
33535abad216da8a49128c3899a206c15d44c471617Ken Shirriff                                Log.e(TAG, this.toString());
3365ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                                throw new OperationApplicationException("Found value " + cursorValue
3375ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                                        + " when expected " + expectedValue + " for column "
3385ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                                        + projection[i]);
3395ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                            }
34008b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey                        }
34108b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey                    }
342ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana                }
343ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            } finally {
344ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana                cursor.close();
345ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            }
346ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        } else {
34735abad216da8a49128c3899a206c15d44c471617Ken Shirriff            Log.e(TAG, this.toString());
348ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            throw new IllegalStateException("bad type, " + mType);
349ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
350ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
351ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        if (mExpectedCount != null && mExpectedCount != numRows) {
35235abad216da8a49128c3899a206c15d44c471617Ken Shirriff            Log.e(TAG, this.toString());
353ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            throw new OperationApplicationException("wrong number of rows: " + numRows);
354ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
355ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
356ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        return new ContentProviderResult(numRows);
357ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    }
358ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
359ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    /**
360ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * The ContentValues back references are represented as a ContentValues object where the
361ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * key refers to a column and the value is an index of the back reference whose
362ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * valued should be associated with the column.
363d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato     * <p>
364d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato     * This is intended to be a private method but it is exposed for
365d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato     * unit testing purposes
366ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param backRefs an array of previous results
367ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param numBackRefs the number of valid previous results in backRefs
368ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @return the ContentValues that should be used in this operation application after
369ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * expansion of back references. This can be called if either mValues or mValuesBackReferences
370ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * is null
371ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     */
372ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    public ContentValues resolveValueBackReferences(
373ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            ContentProviderResult[] backRefs, int numBackRefs) {
374ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        if (mValuesBackReferences == null) {
375ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            return mValues;
376ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
377ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        final ContentValues values;
378ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        if (mValues == null) {
379ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            values = new ContentValues();
380ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        } else {
381ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            values = new ContentValues(mValues);
382ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
383ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        for (Map.Entry<String, Object> entry : mValuesBackReferences.valueSet()) {
384ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            String key = entry.getKey();
385ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            Integer backRefIndex = mValuesBackReferences.getAsInteger(key);
386ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            if (backRefIndex == null) {
38735abad216da8a49128c3899a206c15d44c471617Ken Shirriff                Log.e(TAG, this.toString());
388ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana                throw new IllegalArgumentException("values backref " + key + " is not an integer");
389ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            }
390ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            values.put(key, backRefToValue(backRefs, numBackRefs, backRefIndex));
391ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
392ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        return values;
393ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    }
394ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
395ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    /**
396ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * The Selection Arguments back references are represented as a Map of Integer->Integer where
397ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * the key is an index into the selection argument array (see {@link Builder#withSelection})
398ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * and the value is the index of the previous result that should be used for that selection
399ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * argument array slot.
400d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato     * <p>
401d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato     * This is intended to be a private method but it is exposed for
402d3ad696b1daaa6c92d8fa268c81ce220ed1d9ffcJoe Onorato     * unit testing purposes
403ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param backRefs an array of previous results
404ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param numBackRefs the number of valid previous results in backRefs
405ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @return the ContentValues that should be used in this operation application after
406ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * expansion of back references. This can be called if either mValues or mValuesBackReferences
407ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * is null
408ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     */
409ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    public String[] resolveSelectionArgsBackReferences(
410ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            ContentProviderResult[] backRefs, int numBackRefs) {
411ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        if (mSelectionArgsBackReferences == null) {
412ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            return mSelectionArgs;
413ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
414ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        String[] newArgs = new String[mSelectionArgs.length];
415ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        System.arraycopy(mSelectionArgs, 0, newArgs, 0, mSelectionArgs.length);
416ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        for (Map.Entry<Integer, Integer> selectionArgBackRef
417ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana                : mSelectionArgsBackReferences.entrySet()) {
418ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            final Integer selectionArgIndex = selectionArgBackRef.getKey();
419ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            final int backRefIndex = selectionArgBackRef.getValue();
4208851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana            newArgs[selectionArgIndex] =
4218851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana                    String.valueOf(backRefToValue(backRefs, numBackRefs, backRefIndex));
422ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
423ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        return newArgs;
424ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    }
425ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
42635abad216da8a49128c3899a206c15d44c471617Ken Shirriff    @Override
42735abad216da8a49128c3899a206c15d44c471617Ken Shirriff    public String toString() {
42835abad216da8a49128c3899a206c15d44c471617Ken Shirriff        return "mType: " + mType + ", mUri: " + mUri +
42935abad216da8a49128c3899a206c15d44c471617Ken Shirriff                ", mSelection: " + mSelection +
43035abad216da8a49128c3899a206c15d44c471617Ken Shirriff                ", mExpectedCount: " + mExpectedCount +
43135abad216da8a49128c3899a206c15d44c471617Ken Shirriff                ", mYieldAllowed: " + mYieldAllowed +
43235abad216da8a49128c3899a206c15d44c471617Ken Shirriff                ", mValues: " + mValues +
43335abad216da8a49128c3899a206c15d44c471617Ken Shirriff                ", mValuesBackReferences: " + mValuesBackReferences +
43435abad216da8a49128c3899a206c15d44c471617Ken Shirriff                ", mSelectionArgsBackReferences: " + mSelectionArgsBackReferences;
43535abad216da8a49128c3899a206c15d44c471617Ken Shirriff    }
43635abad216da8a49128c3899a206c15d44c471617Ken Shirriff
437ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    /**
438ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * Return the string representation of the requested back reference.
439ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param backRefs an array of results
440ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param numBackRefs the number of items in the backRefs array that are valid
441ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @param backRefIndex which backRef to be used
442ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @throws ArrayIndexOutOfBoundsException thrown if the backRefIndex is larger than
443ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * the numBackRefs
444ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * @return the string representation of the requested back reference.
445ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     */
44635abad216da8a49128c3899a206c15d44c471617Ken Shirriff    private long backRefToValue(ContentProviderResult[] backRefs, int numBackRefs,
447ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            Integer backRefIndex) {
44803d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana        if (backRefIndex >= numBackRefs) {
44935abad216da8a49128c3899a206c15d44c471617Ken Shirriff            Log.e(TAG, this.toString());
450ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            throw new ArrayIndexOutOfBoundsException("asked for back ref " + backRefIndex
451ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana                    + " but there are only " + numBackRefs + " back refs");
452ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
453ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        ContentProviderResult backRef = backRefs[backRefIndex];
4548851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana        long backRefValue;
455ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        if (backRef.uri != null) {
4568851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana            backRefValue = ContentUris.parseId(backRef.uri);
457ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        } else {
4588851e163fc5bc17d139bf29cd2ec2f3926d342bcFred Quintana            backRefValue = backRef.count;
459ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
460ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        return backRefValue;
461ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    }
462ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
4638943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    public int describeContents() {
4648943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        return 0;
4658943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    }
4668943737692169f564cd34a9c8d471f3a5d438712Fred Quintana
4678943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    public static final Creator<ContentProviderOperation> CREATOR =
4688943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            new Creator<ContentProviderOperation>() {
4698943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        public ContentProviderOperation createFromParcel(Parcel source) {
47003d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana            return new ContentProviderOperation(source);
4718943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        }
4728943737692169f564cd34a9c8d471f3a5d438712Fred Quintana
4738943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        public ContentProviderOperation[] newArray(int size) {
4748943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            return new ContentProviderOperation[size];
4758943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        }
4768943737692169f564cd34a9c8d471f3a5d438712Fred Quintana    };
4778943737692169f564cd34a9c8d471f3a5d438712Fred Quintana
478ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    /**
479ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * Used to add parameters to a {@link ContentProviderOperation}. The {@link Builder} is
480ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * first created by calling {@link ContentProviderOperation#newInsert(android.net.Uri)},
481ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * {@link ContentProviderOperation#newUpdate(android.net.Uri)},
482ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * {@link ContentProviderOperation#newDelete(android.net.Uri)} or
48308b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey     * {@link ContentProviderOperation#newAssertQuery(Uri)}. The withXXX methods
484ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * can then be used to add parameters to the builder. See the specific methods to find for
485ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * which {@link Builder} type each is allowed. Call {@link #build} to create the
486ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     * {@link ContentProviderOperation} once all the parameters have been supplied.
487ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana     */
488ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    public static class Builder {
489ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        private final int mType;
490ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        private final Uri mUri;
491ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        private String mSelection;
492ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        private String[] mSelectionArgs;
493ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        private ContentValues mValues;
494ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        private Integer mExpectedCount;
495ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        private ContentValues mValuesBackReferences;
496ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        private Map<Integer, Integer> mSelectionArgsBackReferences;
49756f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana        private boolean mYieldAllowed;
498ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
499ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        /** Create a {@link Builder} of a given type. The uri must not be null. */
500ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        private Builder(int type, Uri uri) {
501ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            if (uri == null) {
502ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana                throw new IllegalArgumentException("uri must not be null");
503ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            }
504ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            mType = type;
505ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            mUri = uri;
506ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
507ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
5088943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        /** Create a ContentProviderOperation from this {@link Builder}. */
509ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        public ContentProviderOperation build() {
5105ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana            if (mType == TYPE_UPDATE) {
511c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana                if ((mValues == null || mValues.size() == 0)
512c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana                        && (mValuesBackReferences == null || mValuesBackReferences.size() == 0)) {
513c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana                    throw new IllegalArgumentException("Empty values");
514c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana                }
515c933fb663e4748c4fa3f92fc63649e5199519a86Fred Quintana            }
5165ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana            if (mType == TYPE_ASSERT) {
5175ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                if ((mValues == null || mValues.size() == 0)
5185ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                        && (mValuesBackReferences == null || mValuesBackReferences.size() == 0)
5195ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                        && (mExpectedCount == null)) {
5205ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                    throw new IllegalArgumentException("Empty values");
5215ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana                }
5225ab78057a35dc71b2847920031cd707a7e2c6c64Fred Quintana            }
523ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            return new ContentProviderOperation(this);
524ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
525ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
526ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        /**
527ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         * Add a {@link ContentValues} of back references. The key is the name of the column
528ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         * and the value is an integer that is the index of the previous result whose
529ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         * value should be used for the column. The value is added as a {@link String}.
530ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         * A column value from the back references takes precedence over a value specified in
531ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         * {@link #withValues}.
53208b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey         * This can only be used with builders of type insert, update, or assert.
533ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         * @return this builder, to allow for chaining.
534ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         */
535ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        public Builder withValueBackReferences(ContentValues backReferences) {
53608b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey            if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) {
537ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana                throw new IllegalArgumentException(
53808b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey                        "only inserts, updates, and asserts can have value back-references");
539ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            }
540ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            mValuesBackReferences = backReferences;
541ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            return this;
542ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
543ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
544ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        /**
54503d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana         * Add a ContentValues back reference.
54603d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana         * A column value from the back references takes precedence over a value specified in
54703d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana         * {@link #withValues}.
54808b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey         * This can only be used with builders of type insert, update, or assert.
549ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         * @return this builder, to allow for chaining.
550ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         */
55103d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana        public Builder withValueBackReference(String key, int previousResult) {
55208b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey            if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) {
553ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana                throw new IllegalArgumentException(
55408b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey                        "only inserts, updates, and asserts can have value back-references");
555ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            }
55603d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana            if (mValuesBackReferences == null) {
55703d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana                mValuesBackReferences = new ContentValues();
55803d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana            }
55903d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana            mValuesBackReferences.put(key, previousResult);
560ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            return this;
561ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
562ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
563ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        /**
56403d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana         * Add a back references as a selection arg. Any value at that index of the selection arg
56503d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana         * that was specified by {@link #withSelection} will be overwritten.
56608b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey         * This can only be used with builders of type update, delete, or assert.
567ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         * @return this builder, to allow for chaining.
568ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         */
56903d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana        public Builder withSelectionBackReference(int selectionArgIndex, int previousResult) {
57008b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey            if (mType != TYPE_UPDATE && mType != TYPE_DELETE && mType != TYPE_ASSERT) {
57108b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey                throw new IllegalArgumentException("only updates, deletes, and asserts "
57208b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey                        + "can have selection back-references");
573ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            }
57403d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana            if (mSelectionArgsBackReferences == null) {
57503d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana                mSelectionArgsBackReferences = new HashMap<Integer, Integer>();
57603d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana            }
57703d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana            mSelectionArgsBackReferences.put(selectionArgIndex, previousResult);
578ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            return this;
579ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
580ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
581ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        /**
5828943737692169f564cd34a9c8d471f3a5d438712Fred Quintana         * The ContentValues to use. This may be null. These values may be overwritten by
583d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana         * the corresponding value specified by {@link #withValueBackReference} or by
584d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana         * future calls to {@link #withValues} or {@link #withValue}.
58508b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey         * This can only be used with builders of type insert, update, or assert.
5868943737692169f564cd34a9c8d471f3a5d438712Fred Quintana         * @return this builder, to allow for chaining.
5878943737692169f564cd34a9c8d471f3a5d438712Fred Quintana         */
58803d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana        public Builder withValues(ContentValues values) {
58908b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey            if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) {
59008b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey                throw new IllegalArgumentException(
59108b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey                        "only inserts, updates, and asserts can have values");
5928943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            }
593d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            if (mValues == null) {
594d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana                mValues = new ContentValues();
595d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            }
596d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            mValues.putAll(values);
5978943737692169f564cd34a9c8d471f3a5d438712Fred Quintana            return this;
5988943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        }
5998943737692169f564cd34a9c8d471f3a5d438712Fred Quintana
6008943737692169f564cd34a9c8d471f3a5d438712Fred Quintana        /**
601d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana         * A value to insert or update. This value may be overwritten by
602d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana         * the corresponding value specified by {@link #withValueBackReference}.
60308b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey         * This can only be used with builders of type insert, update, or assert.
604d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana         * @param key the name of this value
605d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana         * @param value the value itself. the type must be acceptable for insertion by
606d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana         * {@link ContentValues#put}
607d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana         * @return this builder, to allow for chaining.
608d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana         */
609d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana        public Builder withValue(String key, Object value) {
61008b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey            if (mType != TYPE_INSERT && mType != TYPE_UPDATE && mType != TYPE_ASSERT) {
611d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana                throw new IllegalArgumentException("only inserts and updates can have values");
612d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            }
613d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            if (mValues == null) {
614d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana                mValues = new ContentValues();
615d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            }
616d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            if (value == null) {
617d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana                mValues.putNull(key);
618d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            } else if (value instanceof String) {
619d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana                mValues.put(key, (String) value);
620d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            } else if (value instanceof Byte) {
621d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana                mValues.put(key, (Byte) value);
622d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            } else if (value instanceof Short) {
623d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana                mValues.put(key, (Short) value);
624d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            } else if (value instanceof Integer) {
625d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana                mValues.put(key, (Integer) value);
626d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            } else if (value instanceof Long) {
627d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana                mValues.put(key, (Long) value);
628d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            } else if (value instanceof Float) {
629d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana                mValues.put(key, (Float) value);
630d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            } else if (value instanceof Double) {
631d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana                mValues.put(key, (Double) value);
632d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            } else if (value instanceof Boolean) {
633d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana                mValues.put(key, (Boolean) value);
634d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            } else if (value instanceof byte[]) {
635d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana                mValues.put(key, (byte[]) value);
636d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            } else {
637d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana                throw new IllegalArgumentException("bad value type: " + value.getClass().getName());
638d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            }
639d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana            return this;
640d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana        }
641bc25407b9299ae433023ddf147fe633f3b3b640cJeff Sharkey
642d8dfeb5ee82d679f491cd20e776907a69fb4f27cFred Quintana        /**
643ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         * The selection and arguments to use. An occurrence of '?' in the selection will be
644ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         * replaced with the corresponding occurence of the selection argument. Any of the
645ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         * selection arguments may be overwritten by a selection argument back reference as
64603d9490758c9318cee6d14d3cc5007556dce92d0Fred Quintana         * specified by {@link #withSelectionBackReference}.
64708b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey         * This can only be used with builders of type update, delete, or assert.
648ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         * @return this builder, to allow for chaining.
649ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         */
650ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        public Builder withSelection(String selection, String[] selectionArgs) {
65108b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey            if (mType != TYPE_UPDATE && mType != TYPE_DELETE && mType != TYPE_ASSERT) {
652ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana                throw new IllegalArgumentException(
65308b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey                        "only updates, deletes, and asserts can have selections");
654ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            }
655ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            mSelection = selection;
656824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey            if (selectionArgs == null) {
657824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey                mSelectionArgs = null;
658824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey            } else {
659824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey                mSelectionArgs = new String[selectionArgs.length];
660824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey                System.arraycopy(selectionArgs, 0, mSelectionArgs, 0, selectionArgs.length);
661824838d74eb0316f6987a1d98d2d9e9fa8d4e15bJeff Sharkey            }
662ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            return this;
663ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
664ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana
665ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        /**
666764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown         * If set then if the number of rows affected by this operation does not match
667ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         * this count {@link OperationApplicationException} will be throw.
66808b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey         * This can only be used with builders of type update, delete, or assert.
669ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         * @return this builder, to allow for chaining.
670ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana         */
671ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        public Builder withExpectedCount(int count) {
67208b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey            if (mType != TYPE_UPDATE && mType != TYPE_DELETE && mType != TYPE_ASSERT) {
673ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana                throw new IllegalArgumentException(
67408b75b1ffb856ab97e1577eb7d20c69a18fcaccaJeff Sharkey                        "only updates, deletes, and asserts can have expected counts");
675ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            }
676ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            mExpectedCount = count;
677ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana            return this;
678ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana        }
67956f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana
680764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown        /**
681764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown         * If set to true then the operation allows yielding the database to other transactions
682764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown         * if the database is contended.
683764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown         * @return this builder, to allow for chaining.
684764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown         * @see android.database.sqlite.SQLiteDatabase#yieldIfContendedSafely()
685764e95ec4f92affad448894bd2c4f4067625d3e6Jeff Brown         */
68656f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana        public Builder withYieldAllowed(boolean yieldAllowed) {
68756f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana            mYieldAllowed = yieldAllowed;
68856f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana            return this;
68956f67d21459ad3f136c73c8932904d4a495989c0Fred Quintana        }
690ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana    }
691ce31b2361db630cf1347fa42dd77e610a4eeb96dFred Quintana}
692