1fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey/*
2fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey * Copyright (C) 2010 The Android Open Source Project
3fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey *
4fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey * you may not use this file except in compliance with the License.
6fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey * You may obtain a copy of the License at
7fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey *
8fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey *
10fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
11fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey * See the License for the specific language governing permissions and
14fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey * limitations under the License.
15fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey */
16fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
17fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkeypackage com.android.internal.content;
18fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
19fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkeyimport android.content.ContentValues;
20fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkeyimport android.database.Cursor;
21fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkeyimport android.database.sqlite.SQLiteDatabase;
22fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkeyimport android.text.TextUtils;
23fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
24fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkeyimport java.util.ArrayList;
25fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
26fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey/**
27fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey * Helper for building selection clauses for {@link SQLiteDatabase}. Each
28fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey * appended clause is combined using {@code AND}. This class is <em>not</em>
29fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey * thread safe.
30fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey *
31fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey * @hide
32fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey */
33fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkeypublic class SelectionBuilder {
34fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    private StringBuilder mSelection = new StringBuilder();
35fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    private ArrayList<String> mSelectionArgs = new ArrayList<String>();
36fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
37fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    /**
38fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     * Reset any internal state, allowing this builder to be recycled.
39fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     */
40fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    public SelectionBuilder reset() {
41fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        mSelection.setLength(0);
42fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        mSelectionArgs.clear();
43fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        return this;
44fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    }
45fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
46fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    /**
47fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     * Append the given selection clause to the internal state. Each clause is
48fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     * surrounded with parenthesis and combined using {@code AND}.
49fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     */
500cd57a44ea43ec146722774a3f7d623eb9c9cbb3Jeff Sharkey    public SelectionBuilder append(String selection, Object... selectionArgs) {
51fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        if (TextUtils.isEmpty(selection)) {
52fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey            if (selectionArgs != null && selectionArgs.length > 0) {
53fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey                throw new IllegalArgumentException(
54fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey                        "Valid selection required when including arguments");
55fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey            }
56fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
57fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey            // Shortcut when clause is empty
58fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey            return this;
59fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        }
60fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
61fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        if (mSelection.length() > 0) {
62fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey            mSelection.append(" AND ");
63fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        }
64fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
65fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        mSelection.append("(").append(selection).append(")");
660cd57a44ea43ec146722774a3f7d623eb9c9cbb3Jeff Sharkey        if (selectionArgs != null) {
670cd57a44ea43ec146722774a3f7d623eb9c9cbb3Jeff Sharkey            for (Object arg : selectionArgs) {
680cd57a44ea43ec146722774a3f7d623eb9c9cbb3Jeff Sharkey                // TODO: switch to storing direct Object instances once
690cd57a44ea43ec146722774a3f7d623eb9c9cbb3Jeff Sharkey                // http://b/2464440 is fixed
700cd57a44ea43ec146722774a3f7d623eb9c9cbb3Jeff Sharkey                mSelectionArgs.add(String.valueOf(arg));
710cd57a44ea43ec146722774a3f7d623eb9c9cbb3Jeff Sharkey            }
72fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        }
73fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
74fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        return this;
75fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    }
76fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
77fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    /**
78fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     * Return selection string for current internal state.
79fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     *
80fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     * @see #getSelectionArgs()
81fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     */
82fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    public String getSelection() {
83fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        return mSelection.toString();
84fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    }
85fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
86fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    /**
87fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     * Return selection arguments for current internal state.
88fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     *
89fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     * @see #getSelection()
90fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     */
91fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    public String[] getSelectionArgs() {
92fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        return mSelectionArgs.toArray(new String[mSelectionArgs.size()]);
93fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    }
94fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
95fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    /**
96fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     * Execute query using the current internal state as {@code WHERE} clause.
97fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     * Missing arguments as treated as {@code null}.
98fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     */
99fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    public Cursor query(SQLiteDatabase db, String table, String[] columns, String orderBy) {
100fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        return query(db, table, columns, null, null, orderBy, null);
101fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    }
102fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
103fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    /**
104fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     * Execute query using the current internal state as {@code WHERE} clause.
105fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     */
106fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    public Cursor query(SQLiteDatabase db, String table, String[] columns, String groupBy,
107fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey            String having, String orderBy, String limit) {
108fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        return db.query(table, columns, getSelection(), getSelectionArgs(), groupBy, having,
109fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey                orderBy, limit);
110fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    }
111fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
112fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    /**
113fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     * Execute update using the current internal state as {@code WHERE} clause.
114fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     */
115fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    public int update(SQLiteDatabase db, String table, ContentValues values) {
116fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        return db.update(table, values, getSelection(), getSelectionArgs());
117fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    }
118fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey
119fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    /**
120fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     * Execute delete using the current internal state as {@code WHERE} clause.
121fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey     */
122fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    public int delete(SQLiteDatabase db, String table) {
123fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey        return db.delete(table, getSelection(), getSelectionArgs());
124fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey    }
125fe62d04c30e7b3abe408b56c7744c7f547c57640Jeff Sharkey}
126