content: /*
   * Copyright (C) 2010 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.android.internal.content;
  
  import android.content.ContentValues;
  import android.database.Cursor;
  import android.database.sqlite.SQLiteDatabase;
  import android.text.TextUtils;
  
  import java.util.ArrayList;
  
  /**
   * Helper for building selection clauses for {@link SQLiteDatabase}. Each
   * appended clause is combined using {@code AND}. This class is <em>not</em>
   * thread safe.
   *
   * @hide
   */
  public class SelectionBuilder {
      private StringBuilder mSelection = new StringBuilder();
      private ArrayList<String> mSelectionArgs = new ArrayList<String>();
  
      /**
       * Reset any internal state, allowing this builder to be recycled.
       */
      public SelectionBuilder reset() {
          mSelection.setLength(0);
          mSelectionArgs.clear();
          return this;
      }
  
      /**
       * Append the given selection clause to the internal state. Each clause is
       * surrounded with parenthesis and combined using {@code AND}.
       */
      public SelectionBuilder append(String selection, Object... selectionArgs) {
          if (TextUtils.isEmpty(selection)) {
              if (selectionArgs != null && selectionArgs.length > 0) {
                  throw new IllegalArgumentException(
                          "Valid selection required when including arguments");
              }
  
              // Shortcut when clause is empty
              return this;
          }
  
          if (mSelection.length() > 0) {
              mSelection.append(" AND ");
          }
  
          mSelection.append("(").append(selection).append(")");
          if (selectionArgs != null) {
              for (Object arg : selectionArgs) {
                  // TODO: switch to storing direct Object instances once
                  // http://b/2464440 is fixed
                  mSelectionArgs.add(String.valueOf(arg));
              }
          }
  
          return this;
      }
  
      /**
       * Return selection string for current internal state.
       *
       * @see #getSelectionArgs()
       */
      public String getSelection() {
          return mSelection.toString();
      }
  
      /**
       * Return selection arguments for current internal state.
       *
       * @see #getSelection()
       */
      public String[] getSelectionArgs() {
          return mSelectionArgs.toArray(new String[mSelectionArgs.size()]);
      }
  
      /**
       * Execute query using the current internal state as {@code WHERE} clause.
       * Missing arguments as treated as {@code null}.
       */
      public Cursor query(SQLiteDatabase db, String table, String[] columns, String orderBy) {
          return query(db, table, columns, null, null, orderBy, null);
      }
  
      /**
       * Execute query using the current internal state as {@code WHERE} clause.
       */
      public Cursor query(SQLiteDatabase db, String table, String[] columns, String groupBy,
              String having, String orderBy, String limit) {
          return db.query(table, columns, getSelection(), getSelectionArgs(), groupBy, having,
                  orderBy, limit);
      }
  
      /**
       * Execute update using the current internal state as {@code WHERE} clause.
       */
      public int update(SQLiteDatabase db, String table, ContentValues values) {
          return db.update(table, values, getSelection(), getSelectionArgs());
      }
  
      /**
       * Execute delete using the current internal state as {@code WHERE} clause.
       */
      public int delete(SQLiteDatabase db, String table) {
          return db.delete(table, getSelection(), getSelectionArgs());
      }
  }
  