package vandy.mooc.model; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.text.TextUtils; import android.net.Uri; import android.util.Log; /** * Content Provider implementation that uses SQLite to manage Hobbit * characters. This class plays the role of the "Concrete * Implementor" in the Bridge pattern and the "Concrete Class" in the * TemplateMethod pattern. */ public class HobbitProviderImplSQLite extends HobbitProviderImpl { /** * Use HobbitDatabaseHelper to manage database creation and version * management. */ private HobbitDatabaseHelper mOpenHelper; /** * Constructor initializes the super class. */ public HobbitProviderImplSQLite(Context context) { super(context); } /** * Return true if successfully started. */ public boolean onCreate() { // Create the HobbitDatabaseHelper. mOpenHelper = new HobbitDatabaseHelper(mContext); return true; } /** * Method called to handle insert requests from client * applications. This plays the role of the "concrete hook * method" in the Template Method pattern. */ @Override public Uri insertCharacters(Uri uri, ContentValues cvs) { final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); long id = db.insert(CharacterContract.CharacterEntry.TABLE_NAME, null, cvs); // Check if a new row is inserted or not. if (id > 0) return CharacterContract.CharacterEntry.buildUri(id); else throw new android.database.SQLException ("Failed to insert row into " + uri); } /** * Method that handles bulk insert requests. This plays the role * of the "concrete hook method" in the Template Method pattern. */ @Override public int bulkInsertCharacters(Uri uri, ContentValues[] cvsArray) { // Create and/or open a database that will be used for reading // and writing. Once opened successfully, the database is // cached, so you can call this method every time you need to // write to the database. final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int returnCount = 0; // Begins a transaction in EXCLUSIVE mode. db.beginTransaction(); try { for (ContentValues cvs : cvsArray) { final long id = db.insert(CharacterContract.CharacterEntry.TABLE_NAME, null, cvs); if (id != -1) returnCount++; } // Marks the current transaction as successful. db.setTransactionSuccessful(); } finally { // End a transaction. db.endTransaction(); } return returnCount; } /** * Method called to handle query requests from client * applications. This plays the role of the "concrete hook * method" in the Template Method pattern. */ @Override public Cursor queryCharacters(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Expand the selection if necessary. selection = addSelectionArgs(selection, selectionArgs, "OR"); return mOpenHelper.getReadableDatabase().query (CharacterContract.CharacterEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); } /** * Method called to handle query requests from client * applications. This plays the role of the "concrete hook * method" in the Template Method pattern. */ @Override public Cursor queryCharacter(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Query the SQLite database for the particular rowId based on // (a subset of) the parameters passed into the method. return mOpenHelper.getReadableDatabase().query (CharacterContract.CharacterEntry.TABLE_NAME, projection, addKeyIdCheckToWhereStatement(selection, ContentUris.parseId(uri)), selectionArgs, null, null, sortOrder); } /** * Method called to handle update requests from client * applications. This plays the role of the "concrete hook * method" in the Template Method pattern. */ @Override public int updateCharacters(Uri uri, ContentValues cvs, String selection, String[] selectionArgs) { // Expand the selection if necessary. selection = addSelectionArgs(selection, selectionArgs, " OR "); return mOpenHelper.getWritableDatabase().update (CharacterContract.CharacterEntry.TABLE_NAME, cvs, selection, selectionArgs); } /** * Method called to handle update requests from client * applications. This plays the role of the "concrete hook * method" in the Template Method pattern. */ @Override public int updateCharacter(Uri uri, ContentValues cvs, String selection, String[] selectionArgs) { // Expand the selection if necessary. selection = addSelectionArgs(selection, selectionArgs, " OR "); // Just update a single row in the database. return mOpenHelper.getWritableDatabase().update (CharacterContract.CharacterEntry.TABLE_NAME, cvs, addKeyIdCheckToWhereStatement(selection, ContentUris.parseId(uri)), selectionArgs); } /** * Method called to handle delete requests from client * applications. This plays the role of the "concrete hook * method" in the Template Method pattern. */ @Override public int deleteCharacters(Uri uri, String selection, String[] selectionArgs) { // Expand the selection if necessary. selection = addSelectionArgs(selection, selectionArgs, " OR "); return mOpenHelper.getWritableDatabase().delete (CharacterContract.CharacterEntry.TABLE_NAME, selection, selectionArgs); } /** * Method called to handle delete requests from client * applications. This plays the role of the "concrete hook * method" in the Template Method pattern. */ @Override public int deleteCharacter(Uri uri, String selection, String[] selectionArgs) { // Expand the selection if necessary. selection = addSelectionArgs(selection, selectionArgs, " OR "); // Just delete a single row in the database. return mOpenHelper.getWritableDatabase().delete (CharacterContract.CharacterEntry.TABLE_NAME, addKeyIdCheckToWhereStatement(selection, ContentUris.parseId(uri)), selectionArgs); } /** * Return a selection string that concatenates all the * @a selectionArgs for a given @a selection using the given @a * operation. */ private String addSelectionArgs(String selection, String [] selectionArgs, String operation) { // Handle the "null" case. if (selection == null || selectionArgs == null) return null; else { String selectionResult = ""; // Properly add the selection args to the selectionResult. for (int i = 0; i < selectionArgs.length - 1; ++i) selectionResult += (selection + " = ? " + operation + " "); // Handle the final selection case. selectionResult += (selection + " = ?"); // Output the selectionResults to Logcat. Log.d(TAG, "selection = " + selectionResult + " selectionArgs = "); for (String args : selectionArgs) Log.d(TAG, args + " "); return selectionResult; } } /** * Helper method that appends a given key id to the end of the * WHERE statement parameter. */ private static String addKeyIdCheckToWhereStatement(String whereStatement, long id) { String newWhereStatement; if (TextUtils.isEmpty(whereStatement)) newWhereStatement = ""; else newWhereStatement = whereStatement + " AND "; // Append the key id to the end of the WHERE statement. return newWhereStatement + CharacterContract.CharacterEntry._ID + " = '" + id + "'"; } }