package vandy.mooc.presenter; import java.lang.ref.WeakReference; import vandy.mooc.R; import vandy.mooc.model.CharacterContract; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.RemoteException; import android.widget.SimpleCursorAdapter; import android.widget.Toast; /** * Class that implements the operations for inserting, querying, * updating, and deleting characters from the HobbitContentProvider. * This class plays the role of the "Implementor" in the Bridge * pattern and the "Abstract Class" in the Template Method pattern. * It's also an example of the "External Polymorphism" pattern. */ public abstract class HobbitOpsImpl { /** * Debugging tag used by the Android logger. */ protected final static String TAG = HobbitOpsImpl.class.getSimpleName(); /** * Stores a Weak Reference to the HobbitOps.View so the garbage * collector can remove it when it's not in use. */ protected WeakReference<HobbitOps.View> mHobbitView; /** * Contains the most recent result from a query so the display can * be updated after a runtime configuration change. */ private Cursor mCursor; /** * Hook method dispatched by the GenericActivity framework to * initialize the HobbitOpsImpl object after it's been created. * * @param view The currently active HobbitOps.View. * @param firstTimeIn Set to "true" if this is the first time the * Ops class is initialized, else set to * "false" if called after a runtime * configuration change. */ public void onConfiguration(HobbitOps.View view, boolean firstTimeIn) { // Create a WeakReference to the HobbitView. mHobbitView = new WeakReference<>(view); if (firstTimeIn == false && mCursor != null) // Redisplay the contents of the cursor after a runtime // configuration change. mHobbitView.get().displayCursor(mCursor); } /** * Release resources to prevent leaks. */ public void close() { // No-op. } /** * Return a @a SimpleCursorAdapter that can be used to display the * contents of the Hobbit ContentProvider. */ public SimpleCursorAdapter makeCursorAdapter() { return new SimpleCursorAdapter (mHobbitView.get().getActivityContext(), R.layout.list_layout, null, CharacterContract.CharacterEntry.sColumnsToDisplay, CharacterContract.CharacterEntry.sColumnResIds, 1); } /** * Insert a Hobbit @a character of a particular @a race into the * HobbitContentProvider. Plays the role of a "template method" * in the Template Method pattern. */ public Uri insert(String character, String race) throws RemoteException { final ContentValues cvs = new ContentValues(); // Insert data. cvs.put(CharacterContract.CharacterEntry.COLUMN_NAME, character); cvs.put(CharacterContract.CharacterEntry.COLUMN_RACE, race); // Call to the hook method. return insert(CharacterContract.CharacterEntry.CONTENT_URI, cvs); } /** * Insert @a ContentValues into the HobbitContentProvider at * the @a uri. Plays the role of an "abstract hook method" in the * Template Method pattern. */ protected abstract Uri insert(Uri uri, ContentValues cvs) throws RemoteException; /** * Insert an array of Hobbit @a characters of a particular @a race * into the HobbitContentProvider. Plays the role of a "template * method" in the Template Method pattern. */ public int bulkInsert(String[] characters, String race) throws RemoteException { // Use ContentValues to store the values in appropriate // columns, so that ContentResolver can process it. Since // more than one rows needs to be inserted, an Array of // ContentValues is needed. ContentValues[] cvsArray = new ContentValues[characters.length]; // Index counter. int i = 0; // Insert all the characters into the ContentValues array. for (String character : characters) { ContentValues cvs = new ContentValues(); cvs.put(CharacterContract.CharacterEntry.COLUMN_NAME, character); cvs.put(CharacterContract.CharacterEntry.COLUMN_RACE, race); cvsArray[i++] = cvs; } return bulkInsert (CharacterContract.CharacterEntry.CONTENT_URI, cvsArray); } /** * Insert an array of @a ContentValues into the * HobbitContentProvider at the @a uri. Plays the role of an * "abstract hook method" in the Template Method pattern. */ protected abstract int bulkInsert(Uri uri, ContentValues[] cvsArray) throws RemoteException; /** * Return a Cursor from a query on the HobbitContentProvider at * the @a uri. Plays the role of an "abstract hook method" in the * Template Method pattern. */ public abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) throws RemoteException; /** * Update the @a name and @a race of a Hobbit character at a * designated @a uri from the HobbitContentProvider. Plays the * role of a "template method" in the Template Method pattern. */ public int updateByUri(Uri uri, String name, String race) throws RemoteException { final ContentValues cvs = new ContentValues(); cvs.put(CharacterContract.CharacterEntry.COLUMN_NAME, name); cvs.put(CharacterContract.CharacterEntry.COLUMN_RACE, race); return update(uri, cvs, null, null); } /** * Update the @a race of a Hobbit character with a given * @a name in the HobbitContentProvider. Plays the role of a * "template method" in the Template Method pattern. */ public int updateRaceByName(String name, String race) throws RemoteException { final ContentValues cvs = new ContentValues(); cvs.put(CharacterContract.CharacterEntry.COLUMN_NAME, name); cvs.put(CharacterContract.CharacterEntry.COLUMN_RACE, race); return update(CharacterContract.CharacterEntry.CONTENT_URI, cvs, CharacterContract.CharacterEntry.COLUMN_NAME, new String[] { name }); } /** * Delete the @a selection and @a selectionArgs with the @a * ContentValues in the HobbitContentProvider at the @a uri. * Plays the role of an "abstract hook method" in the Template * Method pattern. */ public abstract int update(Uri uri, ContentValues cvs, String selection, String[] selectionArgs) throws RemoteException; /** * Delete an array of Hobbit @a characterNames from the * HobbitContentProvider. Plays the role of a "template method" * in the Template Method pattern. */ public int deleteByName(String[] characterNames) throws RemoteException { return delete(CharacterContract.CharacterEntry.CONTENT_URI, CharacterContract.CharacterEntry.COLUMN_NAME, characterNames); } /** * Delete an array of Hobbit @a characterRaces from the * HobbitContentProvider. Plays the role of a "template method" * in the Template Method pattern. */ public int deleteByRace(String[] characterRaces) throws RemoteException { return delete(CharacterContract.CharacterEntry.CONTENT_URI, CharacterContract.CharacterEntry.COLUMN_RACE, characterRaces); } /** * Delete the @a selection and @a selectionArgs from the * HobbitContentProvider at the @a uri. Plays the role of an * "abstract hook method" in the Template Method pattern. */ protected abstract int delete(Uri uri, String selection, String[] selectionArgs) throws RemoteException; /** * Delete all characters from the HobbitContentProvider. Plays * the role of a "template method" in the Template Method pattern. */ public int deleteAll() throws RemoteException { return delete(CharacterContract.CharacterEntry.CONTENT_URI, null, null); } /** * Display the current contents of the HobbitContentProvider. */ public void displayAll() throws RemoteException { // Query for all the characters in the HobbitContentProvider. mCursor = query(CharacterContract.CharacterEntry.CONTENT_URI, CharacterContract.CharacterEntry.sColumnsToDisplay, CharacterContract.CharacterEntry.COLUMN_RACE, new String[] { "Dwarf", "Maia", "Hobbit", "Dragon", "Man", "Bear" }, /* The following three null parameters could also be this: null, null, null, */ null); if (mCursor.getCount() == 0) { Toast.makeText(mHobbitView.get().getActivityContext(), "No items to display", Toast.LENGTH_SHORT).show(); // Remove the display if there's nothing left to show. mHobbitView.get().displayCursor (mCursor = null); } else // Display the results of the query. mHobbitView.get().displayCursor (mCursor); } }