Android Open Source - MightyV Episode Data Source






From Project

Back to project page MightyV.

License

The source code is released under:

Apache License

If you think the Android project MightyV listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.indivisible.mightyv.data;
/*www  .  jav a 2s  .  co m*/
import java.util.ArrayList;
import java.util.List;

import com.indivisible.mightyv.util.MyLog;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;

/**
 * Class to handle the interactions between Episode objects and their database.
 * @author indivisible
 */
public class EpisodeDataSource {
  
  //=================================================//
  //    data
  //=================================================//

  private String TAG;
  private SQLiteDatabase db = null;
  private DBMediaOpenHelper dbHelper = null;
  private String[] allColumns = {            //REM update allColumns on activating new fields
      DBMediaOpenHelper.COL_KEY,
      DBMediaOpenHelper.COL_SHOW_FK,
      DBMediaOpenHelper.COL_NUM_EPISODE,
      DBMediaOpenHelper.COL_NUM_SEASON,
      DBMediaOpenHelper.COL_TITLE
    };

  private String SORT_BY_SEASON_THEN_EP =
      DBMediaOpenHelper.COL_NUM_SEASON +" ASC, "+ DBMediaOpenHelper.COL_NUM_EPISODE +" ASC ";
  private String SORT_BY_EPISODE = 
      DBMediaOpenHelper.COL_NUM_EPISODE +" ASC ";
  
  //=================================================//
  //    constructors
  //=================================================//
  
  /**
   * Class to handle the interactions between Episode objects and their database
   * @param context Android ApplicationContext (do not use ActivityContext)
   */
  public EpisodeDataSource(Context context)
  {
    TAG = this.getClass().getSimpleName();        // Get the Class's name for use in the logs
    this.dbHelper = new DBMediaOpenHelper(context); 
  }
  
  
  //=================================================//
  //    open & close db handle
  //=================================================//
  
  /**
   * Open the database in a read-only state.
   * @throws SQLException
   */
  public void openReadable() throws SQLException
  {
    db = dbHelper.getReadableDatabase();
  }
  
  /**
   * Open the database in a writable state.
   * @throws SQLException
   */
  public void openWritable() throws SQLException
  {
    db = dbHelper.getWritableDatabase();
  }
  
  /**
   * Close the database handle
   */
  public void close()
  { 
    if (dbHelper != null) { 
      dbHelper.close();
    }
  }
  
  
  //=================================================//
  //    CRUD
  //=================================================//
  
  //==== Create ====//
  
  /**
   * Create a new Episode object and store it in the database.
   * Returned Episode has its Primary Key within.
   * @param showKey     Episode's parent Show's Primary Key (Foreign Key here)
   * @param seasonNum    The season number containing this Episode
   * @param episodeNum  The episode number of this Episode within the stated season
   * @param title      Episode's title
   * @return Created Episode (retrieved from the database after storing)
   */
  public Episode createEpisode(long showKey, int seasonNum, int episodeNum, String title)
  {
    // format the Episode's details for database entry
    ContentValues values = new ContentValues();
    values.put(DBMediaOpenHelper.COL_SHOW_FK,      showKey);
    values.put(DBMediaOpenHelper.COL_NUM_SEASON,   seasonNum);
    values.put(DBMediaOpenHelper.COL_NUM_EPISODE,  episodeNum);
    values.put(DBMediaOpenHelper.COL_TITLE,        title);
    
    // insert into database and receive new row's key
    long episodeKey = db.insert(DBMediaOpenHelper.TABLE_EPISODES, null, values);
    if (MyLog.debug) MyLog.d(TAG, "Saved Episode. Key: " +episodeKey);
    
    // retrieve saved show from database and return Episode object
    Episode newEpisode =  getEpisodeByKey(episodeKey);
    if (MyLog.verbose) MyLog.v(TAG, "Created new Episode: " +newEpisode.toString());
    return newEpisode;
  }
  
  //==== Read ====//
  
  /**
   * Retrieve a stored Episode from its database identified by its Primary Key (long)
   * @param episodeKey  Episode's Primary Key
   * @return Episode matching Key or NULL on fail
   */
  public Episode getEpisodeByKey(long episodeKey)
  {
    Cursor cursor = null;
    try
    {
      // form and perform a database query
      cursor = db.query(
          DBMediaOpenHelper.TABLE_EPISODES,
          allColumns,
          DBMediaOpenHelper.COL_KEY +" = "+ episodeKey,
          null, null, null, null);
      if (MyLog.debug) MyLog.d(TAG, "Retrieve Episode. Results: " +cursor.getCount());
      // ensure we have only one result
      if (cursor.moveToFirst() && cursor.getCount() == 1)
      {
        Episode episode = cursorToEpisode(cursor);
        if (MyLog.verbose) MyLog.v(TAG, "Retrieved Episode from db: " +episode.toString());
        return episode;
      }
      else
      {
        // return null on fail
        if (MyLog.error) MyLog.e(TAG, "No results in cursor");
        return null;
      }
    }
    finally
    {
      // close cursor regardless of what happens above
      if (cursor != null)
        cursor.close();
    }
  }
  
  /**
   * Retrieve a List of all Episode Primary Keys
   * @return List of Longs of keys (Empty if none)
   */
  public List<Long> getAllEpisodeKeys()
  {
    Cursor cursor = null;
    List<Long> episodeKeys = null;
    try
    {
      // form and perform a database query
      cursor = db.query(
          DBMediaOpenHelper.TABLE_EPISODES,
          new String[] { DBMediaOpenHelper.COL_KEY },
          null, null, null, null, null);
      if (MyLog.verbose) MyLog.v(TAG, "Gathering all Episode keys. Found: " +cursor.getCount());
      // make a List to hold results and iterate through the cursor
      episodeKeys = new ArrayList<Long>();
      if (cursor.moveToFirst())
      {
        while(!cursor.isAfterLast())
        {
          episodeKeys.add(cursor.getLong(0));
          cursor.moveToNext();
        }
      }
      else
      {
        if (MyLog.warn) MyLog.w(TAG, "No results found for all Episode Keys.");
      }
      if (MyLog.verbose) MyLog.v(TAG, "Processed keys: " +episodeKeys.size());
      return episodeKeys;
    }
    finally
    {
      // finally block gets executed even after a method's return statement
      if (cursor != null)
        cursor.close();
    }
  }
  
  /**
   * Retrieve all stored Episodes in the database.
   * Will return every Episode saved and as such should not be used unless explicitly needed.
   * @return List of all Episodes
   */
  public List<Episode> getAllEpisodes()
  {
    Cursor cursor = null;
    List<Episode> episodes = null;
    
    try
    {
      // perform the query on the database
      cursor = db.query(
          DBMediaOpenHelper.TABLE_EPISODES,
          allColumns,
          null, null, null, null, null);    // null 'selection' param returns all rows in table

      // get all result Episodes from the cursor and return the List 
      episodes = getEpisodesFromCursor(cursor);
      if (MyLog.verbose) MyLog.v(TAG, "Episodes parsed and returned: " +episodes.size());
      return episodes;
    }
    finally
    {
      // close the cursor, freeing up its resources
      if (cursor != null)
        cursor.close();
    }
  }
  
  /**
   * Retrieve all Episodes for one particular Show
   * @param showKey Show's Primary Key (a Foreign Key here)
   * @return List of all Episodes for one Show
   */
  public List<Episode> getAllShowsEpisodes(long showKey)
  {
    Cursor cursor = null;
    List<Episode> episodes = null;
    
    try
    {
      // perform the database query
      cursor = db.query(
          DBMediaOpenHelper.TABLE_EPISODES,
          new String[] { DBMediaOpenHelper.COL_KEY },
          DBMediaOpenHelper.COL_SHOW_FK +" = "+ showKey,
          null, null, null,
          SORT_BY_SEASON_THEN_EP);  // get cursor results in a sorted order
      if (MyLog.verbose) MyLog.v(TAG, "Gathering Show's Episodes. Found: " +cursor.getCount());
      
      // get Episodes from cursor and return List
      episodes = getEpisodesFromCursor(cursor);
      return episodes;
    }
    finally
    {
      // free up the cursor's resources
      if (cursor != null)
        cursor.close();
    }
  }
  
  /**
   * Retrieve just the keys for all Episodes belonging to one Show
   * @param showKey Parent Show's Primary Key (a Foreign Key here)
   * @return List of Longs being the Keys
   */
  public List<Long> getAllShowsEpisodeKeys(long showKey)
  {
    Cursor cursor = null;
    List<Long> episodeKeys = null;
    try
    {
      // run the database query
      cursor = db.query(
        DBMediaOpenHelper.TABLE_EPISODES,
        new String[] { DBMediaOpenHelper.COL_KEY },
        DBMediaOpenHelper.COL_SHOW_FK +" = "+ showKey,
        null, null, null, null);
      // put the result keys into a List and return
      if (MyLog.verbose) MyLog.v(TAG, "Gathering Show's Episode Keys. Found: " +cursor.getCount());
      episodeKeys = getKeysFromCursor(cursor);
      return episodeKeys;
    }
    finally
    {
      if (cursor != null)
        cursor.close();
    }
  }
  
  /**
   * Retrieve all Episodes for one Show. Sorts by season and then by episode numbers.
   * @param showId The Foreign Key identifying the Episodes' parent to filter by
   * @return Collection of Episodes
   */
  public List<Episode> getAllEpisodesForShow(long showId)
  {
    Cursor cursor = null;
    List<Episode> episodes = null;
    
    try
    {
      // perform the database query
      cursor = db.query(
          DBMediaOpenHelper.TABLE_EPISODES,
          allColumns,
          DBMediaOpenHelper.COL_SHOW_FK +" = "+ showId,
          null, null, null,
          SORT_BY_SEASON_THEN_EP);  // get cursor results in a sorted order
      if (MyLog.verbose)
      {
        MyLog.v(TAG, "Retrieving Show Episodes for showId: " +showId);
        MyLog.v(TAG, "Found: " +cursor.getCount());
      }
      
      // put Episodes in a List and return it
      episodes = getEpisodesFromCursor(cursor);
      if (MyLog.verbose) MyLog.v(TAG, "Episodes parsed and returned: " +episodes.size());
      return episodes;
    }
    finally
    {
      if (cursor != null)
        cursor.close();
    }
  }
  
  /**
   * Retrieve all Episodes for a single Show's season
   * @param showId Show's Primary Key
   * @param seasonNum Season number
   * @return List of Episodes
   */
  public List<Episode> getAllEpisodesForSeason(long showId, int seasonNum)
  {
    Cursor cursor = null;
    List<Episode> episodes = null;
    
    try
    {
      // form and perform database query
      cursor = db.query(
          DBMediaOpenHelper.TABLE_EPISODES,
          allColumns,
          DBMediaOpenHelper.COL_SHOW_FK +" = "+ showId
            +" AND "+ DBMediaOpenHelper.COL_NUM_SEASON +" = "+ seasonNum, // compound selection
          null, null, null,
          SORT_BY_EPISODE);  // get cursor results in a sorted order
      
      // get Episodes from cursor's results and return in a List
      episodes = getEpisodesFromCursor(cursor);
      if (MyLog.verbose) MyLog.v(TAG, "Episodes parsed and returned: " +episodes.size());
      return episodes;
    }
    finally
    {
      if (cursor != null)
        cursor.close();
    }
  }
  
  
  //TODO future Read methods
  public Episode _getLatestEpisode() {return null;}
  public Episode _getNextUnreleasedEpisode() {return null;}
  public Episode _getLastWatchedEpisode() {return null;}
  public Episode _getNextUnwatchedEpisode() {return null;}
  
  //==== Update ====//
  
  /**
   * Update an Episode's entry in the database
   * @param episode Episode
   * @return boolean indicating successful update
   */
  public boolean updateEpisode(Episode episode)
  {
    // format the Episode's info for database insertion
    ContentValues values = getValuesFromEpisode(episode);
    
    // start a database transaction so we can revert any changes if unhappy with them
    db.beginTransaction();
    try
    {
      // perform the update and get the number of changed rows in return
      int rowsAffected = db.update(
          DBMediaOpenHelper.TABLE_EPISODES,
          values,
          DBMediaOpenHelper.COL_KEY +" = "+ episode.getKey(),
          null);
      // ensure only one row was touched
      if (rowsAffected == 1)
      {
        if (MyLog.verbose) MyLog.v(TAG, "Updated episode: " +episode.toString());
        // tell the database to commit the changes
        db.setTransactionSuccessful();
        return true;
      }
      else
      {
        if (MyLog.error)
        {
          MyLog.e(TAG, "Failed horribly while attempting to save Episode: " +episode.toString());
          MyLog.e(TAG, "Rows affected: " +rowsAffected);
        }
        // do not setTransactionSuccessful. changes will be reverted
        return false;
      }
    }
    finally
    {
      // terminate the transaction. if setTransactionSuccessful changes will be saved.
      db.endTransaction();
    }
  }
  
  //==== Delete ====//
  
  /**
   * Delete an Episode's database entry identified by its Primary Key (long)
   * @param episodeKey The Episode to be deleted's Primary Key
   * @return boolean indicating successful deletion
   */
  private boolean deleteEpisode(long episodeKey)
  {
    // start database transaction to allow us to revert changes if something goes wrong
    db.beginTransaction();
    try
    {
      // perform the delete and get the number of rows removed
      int rowsAffected = db.delete(
          DBMediaOpenHelper.TABLE_EPISODES, 
          DBMediaOpenHelper.COL_KEY +" = "+ episodeKey,
          null);
      // ensure only one row was touched
      if (rowsAffected == 1)
      {
        if (MyLog.verbose) MyLog.v(TAG, "Deleted Episode with Key: " +episodeKey);
        // save the changes made (row deleted)
        db.setTransactionSuccessful();
        return true;
      }
      else
      {
        if (MyLog.warn)
        {
          MyLog.w(TAG, "Tried to delete Episode but it didn't go to plan. episodeKey: " +episodeKey);
          MyLog.w(TAG, "Rows affected: " +rowsAffected);
        }
        // revert all changes as didn't setTransactionSuccessful
        return false;
      }
    }
    finally
    {
      // complete transaction
      db.endTransaction();
    }
  }
  
  /**
   * Delete a single Episode
   * @param episodeKey Primary Key of Episode
   * @return successful deletion of Episode
   */
  public boolean deleteOneEpisode(long episodeKey)
  {
    // start database transaction
    db.beginTransaction();
    try
    {
      // perform delete and branch by success
      boolean successfulDelete = deleteEpisode(episodeKey);
      if (successfulDelete)
      {
        if (MyLog.verbose) MyLog.v(TAG, "Successfully deleted single Episode: " +episodeKey);
        db.setTransactionSuccessful();
        return true;
      }
      else
      {
        if (MyLog.error) MyLog.e(TAG, "Failed to delete single Episode: " +episodeKey);
        return false;
      }
    }
    finally
    {
      // end transaction
      db.endTransaction();
    }
    
  }
  
  /**
   * Delete a number of Episodes at once
   * @param episodeKeys List of Episode Primary Keys to delete
   * @return List of Longs of any failed deletes. Changes not saved unless List is empty
   */
  public List<Long> deleteMultipleEpisodes(List<Long> episodeKeys)
  {
    if (MyLog.debug) MyLog.d(TAG, "Delete multiple Episodes...\n Recieved Keys: " +episodeKeys.size());
    List<Long> failedDeletes = new ArrayList<Long>();
    
    //ASK do or don't commit deletes if any fail?
    db.beginTransaction();
    try
    {
      for (Long key : episodeKeys)
      {
        // delete each Episode by Key and add failed deletions to List
        if (!deleteEpisode(key))
        {
          failedDeletes.add(key);
        }
        else
        {
          // successful delete
        }
      }
      if (failedDeletes.size() == 0)
      {
        // if all individual deletions were successful overall deletion was a success
        if (MyLog.verbose) MyLog.v(TAG, "Deleted Episodes successfully. Count: " +episodeKeys.size());
        db.setTransactionSuccessful();
      }
      else
      {
        // not all deletes were successful. do not commit changes, log failures to console
        if (MyLog.error) MyLog.e(TAG, "Could not delete all Episodes -");
        if (MyLog.warn)
        {
          for (Long failedKey : failedDeletes)
          {
            MyLog.w(TAG, "Failed: " +failedKey);
          }
        }
      }
    }
    finally
    {
      // complete transaction
      db.endTransaction();
    }
    // return List of keys that failed to delete. Empty on success (and saved changes)
    return failedDeletes;
  }
  
  /**
   * Delete ALL Episodes in the database
   * @return List of Episode keys that didn't delete. Changes reverted if non empty.
   */
  public boolean deleteAllEpisodes()
  {
    // collect all Episode Keys. 
    List<Long> allEpisodeKeys = getAllEpisodeKeys();
    if (MyLog.debug) MyLog.d(TAG, "All Episodes. Found: " +allEpisodeKeys.size());
    
    // delete those Episodes
    List<Long> failedDeletes = deleteMultipleEpisodes(allEpisodeKeys);
    // test if deletion successful and return boolean
    if (failedDeletes.size() == 0)
    {
      if (MyLog.info) MyLog.i(TAG, "Successfully deleted ALL Episodes");
      return true;
    }
    else
    {
      if (MyLog.error) MyLog.e(TAG, "Couldn't delete some Episodes. Total: " +failedDeletes.size());
      return false;
    }
  }
  
  /**
   * Delete all episodes belonging to just one Show
   * @param showKey Show's Primary Key
   * @return successfully deleted all episodes
   */
  public boolean deleteAllShowsEpisodes(long showKey)
  {
    // get the Keys for all Episodes belonging to the Show
    List<Long> episodeKeys = getAllShowsEpisodeKeys(showKey);
    // attempt to delete all its Episodes.
    List<Long> failedDeletes = deleteMultipleEpisodes(episodeKeys);
    
    // test if deletion successful
    if (failedDeletes.size() == 0)
    {
      if (MyLog.info) MyLog.i(TAG, "Deleted all Episodes for Show: " +showKey);
      return true;
    }
    else
    {
      if (MyLog.verbose) MyLog.v(TAG, "Failed to delete all Episodes for Show: " +showKey);;
      return false;
    }
  }
  
//  public boolean deleteAllSeasonsEpisodes(long showKey, int seasonNum)
//  {
//    
//  }
  
  //=================================================//
  //    private methods
  //=================================================//
  
  /**
   * Craft a single Episode object from a Cursor's current result
   * @param cursor Database query Cursor set to desired position
   * @return Episode or NULL on failure
   */
  private static Episode cursorToEpisode(Cursor cursor)
  {
    // Note: relies on cursor's query requesting allColumns.
    Episode ep = null;
    try
    {
      ep = new Episode();
      ep.setKey(cursor.getLong(0));
      ep.setParentKey(cursor.getLong(1));
      ep.setSeasonNum(cursor.getInt(2));
      ep.setEpisodeNum(cursor.getInt(3));
      ep.setTitle(cursor.getString(4));
    }
    catch (NumberFormatException e)
    {
      if (MyLog.error) MyLog.e("EpisodeDataSource", "Failed to get Episode from cursor result.");
    }
    //ASK also catch column number out of bounds?
    
    return ep;
  }
  
  /**
   * Extract and prepare an Episode's values for database entry
   * @param episode Episode to prepare for database entry
   * @return ContentValues
   */
  private static ContentValues getValuesFromEpisode(Episode episode)
  {
    ContentValues values = new ContentValues();
    values.put(DBMediaOpenHelper.COL_SHOW_FK, episode.getParentKey());
    values.put(DBMediaOpenHelper.COL_NUM_SEASON, episode.getSeasonNum());
    values.put(DBMediaOpenHelper.COL_NUM_EPISODE, episode.getEpisodeNum());
    values.put(DBMediaOpenHelper.COL_TITLE, episode.getTitle());
    return values;
  }
  
  /**
   * Private method to iterate through a Cursor's result rows and create a List of Episode objects
   * @param cursor Query result cursor
   * @return Collection of Episodes
   */
  private static List<Episode> getEpisodesFromCursor(Cursor cursor)
  {
    List<Episode> episodes = new ArrayList<Episode>();
    
    // ensure there are results and move cursor to the first one
    if(cursor.moveToFirst())
    {
      // iterate through results and add Episodes to the List
      Episode ep;
      while (!cursor.isAfterLast())
      {
        ep = cursorToEpisode(cursor);
        episodes.add(ep);
        cursor.moveToNext();
      }
    }
    else
    {
      // there were no result rows found
      if (MyLog.warn) MyLog.w("EpisodeDataSource", "No results to extract from cursor");
    }
    // return Episodes. Empty if cursor empty.
    return episodes;
  }
  
  /**
   * Retrieve all Primary Keys from a cursor query.
   * Query must have key as column 0.
   * @param cursor
   * @return
   */
  private static List<Long> getKeysFromCursor(Cursor cursor)
  {
    List<Long> episodeKeys = new ArrayList<Long>();
    
    // ensure there are results and move cursor to the first one
    if (cursor.moveToFirst())
    {
      // iterate through the results and add Keys to the List
      while (!cursor.isAfterLast())
      {
        episodeKeys.add(cursor.getLong(0));
        cursor.moveToNext();
      }
    }
    else
    {
      // no results found
      if (MyLog.warn) MyLog.w("EpisodeDataSource", "No Keys to extract from cursor");
    }
    // return found Keys. Empty if cursor empty
    return episodeKeys;
  }
  
}




Java Source Code List

com.indivisible.mightyv.activities.ShowAddActivity.java
com.indivisible.mightyv.activities.ShowSearchActivity.java
com.indivisible.mightyv.activities.testing.TestEpisodes.java
com.indivisible.mightyv.activities.testing.TestMenu.java
com.indivisible.mightyv.activities.testing.TestSearch.java
com.indivisible.mightyv.activities.testing.TestShows.java
com.indivisible.mightyv.data.DBMediaOpenHelper.java
com.indivisible.mightyv.data.EpisodeDataSource.java
com.indivisible.mightyv.data.Episode.java
com.indivisible.mightyv.data.ShowDataSource.java
com.indivisible.mightyv.data.Show.java
com.indivisible.mightyv.dialogs.SearchShowEntryDialog.java
com.indivisible.mightyv.dialogs.SearchShowResultsDialog.java
com.indivisible.mightyv.dialogs.SelectShowDialog.java
com.indivisible.mightyv.fragments.EpisodeListFragment.java
com.indivisible.mightyv.fragments.ShowAddButtonsFragment.java
com.indivisible.mightyv.fragments.ShowListFragment.java
com.indivisible.mightyv.fragments.ShowRageSearchFragment.java
com.indivisible.mightyv.util.Convert.java
com.indivisible.mightyv.util.EpisodeArrayAdapter.java
com.indivisible.mightyv.util.MyLog.java
com.indivisible.mightyv.util.ShowArrayAdapter.java
com.tvrage.api.EpisodeListXMLParser.java
com.tvrage.api.SearchXMLParser.java
com.tvrage.api.XMLParser.java