Android Open Source - DroidSweeper D S D B Adapter






From Project

Back to project page DroidSweeper.

License

The source code is released under:

MIT License

If you think the Android project DroidSweeper 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 de.nisble.droidsweeper.game.database;
//from   w w w . java 2  s  . c  om
import java.util.ArrayList;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteDatabase;
import de.nisble.droidsweeper.config.Constants;
import de.nisble.droidsweeper.config.Level;
import de.nisble.droidsweeper.game.database.DSDBContract.GameTable;
import de.nisble.droidsweeper.game.replay.Replay;
import de.nisble.droidsweeper.utilities.LogDog;
import static de.nisble.droidsweeper.game.database.DSDBContract.*;

/** Adapter to ease the access to the database.
 * @author Moritz Nisbl moritz.nisble@gmx.de */
public final class DSDBAdapter {
  private static final String CLASSNAME = DSDBAdapter.class.getSimpleName();

  public static final DSDBAdapter INSTANCE = new DSDBAdapter();

  private DSDBHelper mHelper = null;

  private DSDBAdapter() {
  }

  /** Initialization.
   * @note Method isn't thread-safe.
   * @param context Androids application context. */
  public DSDBAdapter open(Context context) {
    if (mHelper == null) {
      mHelper = new DSDBHelper(context);
    }
    return this;
  }

  public void close() {
    if (mHelper != null)
      mHelper.close();
  }

  /** Get all stored games for a specific difficulty without the replay data.
   * @param difficulty The difficulty.
   * @return A with all entries for the given difficulty.
   * @throws Exception On unknown difficulty. */
  public ArrayList<DSDBGameEntry> getGames(Level level) throws Exception {
    if (Level.CUSTOM == level) {
      throw new IllegalArgumentException("No database entries for custom difficulty levels");
    }

    ArrayList<DSDBGameEntry> result = new ArrayList<DSDBGameEntry>();
    SQLiteDatabase db = mHelper.getReadableDatabase();

    Cursor c = db.rawQuery("SELECT * FROM " + GamesView.VIEW_NAME + " WHERE " + GamesView.CN_LEVEL + "=? "
        + " ORDER BY " + GamesView.CN_TIME + ", " + GamesView.CN_DATE,
        new String[] { String.valueOf(level.ordinal()) });
    try {
      if (c.moveToFirst()) {
        while (!c.isAfterLast()) {
          DSDBGameEntry entry = new DSDBGameEntry(c.getLong(c.getColumnIndexOrThrow(GamesView._ID)), level,
              c.getString(c.getColumnIndexOrThrow(GamesView.CN_NAME)), c.getLong(c
                  .getColumnIndexOrThrow(GamesView.CN_TIME)), c.getLong(c
                  .getColumnIndexOrThrow(GamesView.CN_DATE)), null);

          result.add(entry);
          c.moveToNext();
        }
      } else {
        LogDog.d(CLASSNAME, "No entries available for level: " + level.toString());
      }
    } finally {
      c.close();
    }

    return result;
  }

  public DSDBGameEntry getReplay(long gameID) throws Exception {
    DSDBGameEntry entry = null;
    SQLiteDatabase db = mHelper.getReadableDatabase();

    Cursor c = db.rawQuery("SELECT * FROM " + GamesView.VIEW_NAME + " WHERE " + GamesView._ID + "=? ",
        new String[] { String.valueOf(gameID) });

    try {
      if (c.moveToFirst()) {
        // Create an entry object with the information from GameView
        entry = new DSDBGameEntry(c.getLong(c.getColumnIndexOrThrow(GamesView._ID)), Level.fromInt(c.getInt(c
            .getColumnIndexOrThrow(GamesView.CN_LEVEL))), c.getString(c
            .getColumnIndexOrThrow(GamesView.CN_NAME)), c.getLong(c
            .getColumnIndexOrThrow(GamesView.CN_TIME)), c.getLong(c
            .getColumnIndexOrThrow(GamesView.CN_DATE)), null);
      } else {
        throw new IllegalArgumentException("Unable to query replay for ID " + gameID);
      }
    } finally {
      c.close();
    }

    // Use getReplay(DSDBGameEntry entry) to query the replay
    return getReplay(entry);
  }

  /** Get the replay for a given DBEntry.
   * @note The returned entry is not the same as the one passed in.
   *       Not thread-safe!
   * @param entry The entry to query the replay for.
   * @return A new entry including the replay data. */
  public DSDBGameEntry getReplay(DSDBGameEntry entry) throws Exception {
    if (Level.CUSTOM == entry.LEVEL) {
      throw new IllegalArgumentException("No database entries for custom difficulty levels");
    }

    DSDBGameEntry result = null;
    SQLiteDatabase db = mHelper.getReadableDatabase();

    /* ID is sufficient for where clause. */
    Cursor c = db.query(GameTable.TABLE_NAME, new String[] { GameTable._ID, GameTable.CN_REPLAY }, GameTable._ID
        + "=?", new String[] { String.valueOf(entry.GAMEID) }, null, null, null);
    try {
      if (c.moveToFirst()) {
        /* Create a new entry from the given one and add the replay */
        result = new DSDBGameEntry(entry.GAMEID, entry.LEVEL, entry.NAME, entry.PLAYTIME, entry.EPOCHTIME,
            c.getBlob(c.getColumnIndex(GameTable.CN_REPLAY)));
      } else {
        throw new IllegalArgumentException("Unable to query replay for ID " + entry.GAMEID);
      }
    } finally {
      c.close();
    }

    return result;
  }

  /** Check if a time would be inserted or not. The database isn't changed.
   * @param difficulty The difficulty.
   * @param milliseconds The time in ms.
   * @return True on insert, else false. */
  public boolean isHighScore(Level level, long milliseconds) throws Exception {
    if (Level.CUSTOM == level) {
      throw new IllegalArgumentException("No database entries for custom difficulty levels");
    }

    boolean result = false;
    SQLiteDatabase db = mHelper.getReadableDatabase();

    Cursor c = db.rawQuery("SELECT " + Level4GameView.CN_TIME + " FROM " + Level4GameView.VIEW_NAME + " WHERE "
        + Level4GameView.CN_LEVEL + "=? " + " ORDER BY " + Level4GameView.CN_TIME + ", "
        + Level4GameView.CN_DATE, new String[] { String.valueOf(level.ordinal()) });

    try {
      if (!c.moveToLast() || (c.getCount() < Constants.MAX_HIGHSCORES)
          || milliseconds < c.getLong(c.getColumnIndexOrThrow(Level4GameView.CN_TIME))) {
        /* Highscore when: Less than 10 entries. Move to last is false
         * (means there are no entries! If it is true we are now on the
         * last entry.) The new time is faster (<) than the last
         * one. (That means: No highscore on equal times. That should be
         * the expected behavior.) */
        result = true;
      }
    } finally {
      c.close();
    }

    return result;
  }

  private void deleteExcessGames(Level level) {
    SQLiteDatabase db = mHelper.getWritableDatabase();

    /* Statement for getting all games for the given level.
     * The ID is the one from the game table. */
    String sqlGames = "SELECT " + Level4GameView._ID + ", " + Level4GameView.CN_GAMEPLAYER + " FROM "
        + Level4GameView.VIEW_NAME + " WHERE " + Level4GameView.CN_LEVEL + "="
        + String.valueOf(level.ordinal()) + " ORDER BY " + Level4GameView.CN_TIME + ", "
        + Level4GameView.CN_DATE;

    Cursor c = null;
    try {
      /* Query in loop while the cursor isn't empty and the count of games
       * is bigger than the configured maximum */
      while ((c = db.rawQuery(sqlGames, null)).moveToLast() && c.getCount() > Constants.MAX_HIGHSCORES) {
        int result = 0;

        long gameID = c.getLong(c.getColumnIndexOrThrow(Level4GameView._ID));
        /* Save the playerID foreign key */
        long playerID = c.getLong(c.getColumnIndexOrThrow(Level4GameView.CN_GAMEPLAYER));

        /* Delete the game */
        result = db.delete(GameTable.TABLE_NAME, GameTable._ID + "=" + gameID, null);
        if (result > 0)
          LogDog.i(CLASSNAME, "Game " + gameID + " dropped.");

        /* Try to delete the player. DBMS restricts this when there are
         * other games referencing this player! */
        try {
          result = db.delete(PlayerTable.TABLE_NAME, PlayerTable._ID + "=" + playerID, null);
          if (result > 0)
            LogDog.i(CLASSNAME, "Player " + playerID + " dropped.");
        } catch (SQLiteConstraintException e) {
          LogDog.i(CLASSNAME, "Unable to drop player " + playerID + ". Player is still referenced by other games.");
        }
      }
    } finally {
      if (c != null)
        c.close();
    }

  }

  /** Insert a new entry.
   * @note Database removes the slowest time by trigger when more than 10
   *       entries are made. Use isHighscore() to check if the time would be
   *       inserted before a call to this function.
   * @param entry An entry.
   * @throws Exception On unknown difficulty.
   * @return The ID of the inserted game. */
  public long insertTime(Replay replay) throws Exception {
    if (Level.CUSTOM == replay.getGameConfig().LEVEL) {
      throw new IllegalArgumentException("No database entries for custom difficulty levels");
    } else if (0 == replay.getName().length()) {
      throw new IllegalArgumentException("No player name set!");
    }

    ContentValues values = new ContentValues();
    long playerID = -1;
    long gameID = -1;
    SQLiteDatabase db = mHelper.getWritableDatabase();

    // Query player name
    Cursor c = db.query(PlayerTable.TABLE_NAME, new String[] { PlayerTable._ID, PlayerTable.CN_NAME },
        PlayerTable.CN_NAME + "=?", new String[] { replay.getName() }, null, null, null);

    /* Use a transaction to not pollute the player table with names
     * that are not linked with a game, if something goes wrong and the
     * game insert fails. */
    db.beginTransaction();
    try {
      /* Check whether the cursor is empty */
      if (!c.moveToFirst()) {
        /* Empty! Player name not found. Insert new one. */
        values.put(PlayerTable.CN_NAME, replay.getName());
        playerID = db.insertOrThrow(PlayerTable.TABLE_NAME, null, values);
        values.clear();
      } else if (c.getCount() > 1) {
        throw new SQLException("Player table inconsistant. Broken or manipulated database.");
      } else {
        /* Player name found. Store row id. */
        playerID = c.getLong(c.getColumnIndexOrThrow(PlayerTable._ID));
      }

      /* A query for the level is redundant. The level number is the
       * foreign key! */
      values.put(GameTable.CN_GAMELEVEL, replay.getGameConfig().LEVEL.ordinal());
      values.put(GameTable.CN_GAMEPLAYER, playerID);
      values.put(GameTable.CN_TIME, replay.getPlayTime());
      values.put(GameTable.CN_DATE, replay.getEpochTime());
      values.put(GameTable.CN_REPLAY, replay.serializeTimeSteps());

      gameID = db.insertOrThrow(GameTable.TABLE_NAME, null, values);

      db.setTransactionSuccessful();
    } finally {
      db.endTransaction();
      c.close();
    }

    deleteExcessGames(replay.getGameConfig().LEVEL);

    return gameID;
  }
}




Java Source Code List

de.nisble.droidsweeper.config.ApplicationConfig.java
de.nisble.droidsweeper.config.Constants.java
de.nisble.droidsweeper.config.GameConfig.java
de.nisble.droidsweeper.config.Level.java
de.nisble.droidsweeper.game.Field.java
de.nisble.droidsweeper.game.GameObserver.java
de.nisble.droidsweeper.game.Game.java
de.nisble.droidsweeper.game.Position.java
de.nisble.droidsweeper.game.database.DSDBAdapter.java
de.nisble.droidsweeper.game.database.DSDBContract.java
de.nisble.droidsweeper.game.database.DSDBGameEntry.java
de.nisble.droidsweeper.game.database.DSDBHelper.java
de.nisble.droidsweeper.game.jni.FieldListener.java
de.nisble.droidsweeper.game.jni.FieldStatus.java
de.nisble.droidsweeper.game.jni.GameStatus.java
de.nisble.droidsweeper.game.jni.MatrixObserver.java
de.nisble.droidsweeper.game.jni.MineSweeperMatrix.java
de.nisble.droidsweeper.game.replay.PlayerObserver.java
de.nisble.droidsweeper.game.replay.Player.java
de.nisble.droidsweeper.game.replay.Recorder.java
de.nisble.droidsweeper.game.replay.Replay.java
de.nisble.droidsweeper.game.replay.TimeStep.java
de.nisble.droidsweeper.gui.DroidSweeperActivity.java
de.nisble.droidsweeper.gui.HighScoreActivity.java
de.nisble.droidsweeper.gui.HighScoreListAdapter.java
de.nisble.droidsweeper.gui.SettingsActivity.java
de.nisble.droidsweeper.gui.grid.FieldDrawables.java
de.nisble.droidsweeper.gui.grid.FieldView.java
de.nisble.droidsweeper.gui.grid.GameGridView.java
de.nisble.droidsweeper.utilities.LogDog.java
de.nisble.droidsweeper.utilities.Timer.java