package com.ioabsoftware.gameraven.db; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.DatabaseUtils; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import com.ioabsoftware.gameraven.AllInOneV2; import com.ioabsoftware.gameraven.BuildConfig; import com.ioabsoftware.gameraven.networking.NetDesc; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.zip.Deflater; import java.util.zip.Inflater; public class HistoryDBAdapter { private static final String DATABASE_NAME = "history.db"; private static final int DATABASE_VERSION = 3; public static final String TABLE_HISTORY = "history"; public static final String COLUMN_HIST_ID = "_id"; public static final String COLUMN_HIST_PATH = "path"; public static final String COLUMN_HIST_DESC = "desc"; public static final String COLUMN_HIST_SRC = "src"; public static final String COLUMN_HIST_VLOC_FIRSTVIS = "vlocfirstvis"; public static final String COLUMN_HIST_VLOC_OFFSET = "vlocoffset"; private static final String CREATE_TABLE_HISTORY = "create table if not exists " + TABLE_HISTORY + "(" + COLUMN_HIST_ID + " integer primary key autoincrement, " + COLUMN_HIST_PATH + " text not null, " + COLUMN_HIST_DESC + " text not null, " + COLUMN_HIST_SRC + " blob not null, " + COLUMN_HIST_VLOC_FIRSTVIS + " integer not null, " + COLUMN_HIST_VLOC_OFFSET + " integer not null);"; private boolean hasHistory = false; private String lastAddedPath = AllInOneV2.EMPTY_STRING; private DatabaseHelper dbHelper; private static class DatabaseHelper extends SQLiteOpenHelper { private static DatabaseHelper sInstance; DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_TABLE_HISTORY); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_HISTORY); onCreate(db); } public static DatabaseHelper getInstance(Context context) { // Use the application context, which will ensure that you // don't accidentally leak an Activity's context. // See this article for more information: http://bit.ly/6LRzfx if (sInstance == null) { sInstance = new DatabaseHelper(context.getApplicationContext()); } return sInstance; } } public HistoryDBAdapter open(Context context) { dbHelper = DatabaseHelper.getInstance(context); dbHelper.getWritableDatabase(); updateHasHistory(); return this; } public void close() { dbHelper.close(); } public void clearTable() { dbHelper.getWritableDatabase().delete(TABLE_HISTORY, null, null); updateHasHistory(); } public void insertHistory(String pathIn, String descIn, byte[] srcIn, int vLocFirstVisIn, int vLocOffsetIn) { if (!lastAddedPath.equals(pathIn)) { if (BuildConfig.DEBUG) AllInOneV2.wtl("starting insert history method"); lastAddedPath = pathIn; if (BuildConfig.DEBUG) AllInOneV2.wtl("creating content vals obj"); ContentValues vals = new ContentValues(); if (BuildConfig.DEBUG) AllInOneV2.wtl("putting content vals"); vals.put(COLUMN_HIST_PATH, pathIn); vals.put(COLUMN_HIST_DESC, descIn); vals.put(COLUMN_HIST_SRC, compress(srcIn)); vals.put(COLUMN_HIST_VLOC_FIRSTVIS, vLocFirstVisIn); vals.put(COLUMN_HIST_VLOC_OFFSET, vLocOffsetIn); if (BuildConfig.DEBUG) AllInOneV2.wtl("inserting row"); dbHelper.getWritableDatabase().insert(TABLE_HISTORY, null, vals); if (BuildConfig.DEBUG) AllInOneV2.wtl("trimming history"); trimHistory(); if (BuildConfig.DEBUG) AllInOneV2.wtl("updating hasHistory"); updateHasHistory(); if (BuildConfig.DEBUG) AllInOneV2.wtl("insert history method completing"); } } public History pullHistory() { Cursor cur = dbHelper.getWritableDatabase().query(TABLE_HISTORY, null, null, null, null, null, COLUMN_HIST_ID + " DESC", "2"); cur.moveToFirst(); long id = cur.getLong(0); String path = cur.getString(1); History h = new History(path, NetDesc.valueOf(cur.getString(2)), decompress(cur.getBlob(3)), new int[]{cur.getInt(4), cur.getInt(5)}); if (cur.moveToNext()) lastAddedPath = cur.getString(1); else lastAddedPath = AllInOneV2.EMPTY_STRING; cur.close(); dbHelper.getWritableDatabase().delete(TABLE_HISTORY, COLUMN_HIST_ID + " = " + id, null); updateHasHistory(); return h; } private void trimHistory() { while (DatabaseUtils.queryNumEntries(dbHelper.getWritableDatabase(), TABLE_HISTORY) > 15) { Cursor cur = dbHelper.getWritableDatabase().query(TABLE_HISTORY, new String[]{COLUMN_HIST_ID}, null, null, null, null, COLUMN_HIST_ID, "1"); cur.moveToFirst(); long id = cur.getLong(0); cur.close(); dbHelper.getWritableDatabase().delete(TABLE_HISTORY, COLUMN_HIST_ID + " = " + id, null); } } private void updateHasHistory() { hasHistory = DatabaseUtils.queryNumEntries(dbHelper.getWritableDatabase(), TABLE_HISTORY) > 0; } public boolean hasHistory() { return hasHistory; } public static byte[] compress(byte[] data) { if (BuildConfig.DEBUG) AllInOneV2.wtl("starting history compression"); try { Deflater deflater = new Deflater(Deflater.BEST_SPEED); deflater.setInput(data); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length); deflater.finish(); byte[] buffer = new byte[1024]; while (!deflater.finished()) { int count = deflater.deflate(buffer); // returns the generated code... index outputStream.write(buffer, 0, count); } deflater.end(); outputStream.close(); byte[] output = outputStream.toByteArray(); if (BuildConfig.DEBUG) AllInOneV2.wtl("CMPRSSN - Original: " + data.length / 1024 + " Kb"); if (BuildConfig.DEBUG) AllInOneV2.wtl("CMPRSSN - Compressed: " + output.length / 1024 + " Kb"); return output; } catch (IOException e) { e.printStackTrace(); return data; } } public static byte[] decompress(byte[] data) { if (BuildConfig.DEBUG) AllInOneV2.wtl("starting history decompression"); try { Inflater inflater = new Inflater(); inflater.setInput(data); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length); byte[] buffer = new byte[1024]; while (!inflater.finished()) { int count = inflater.inflate(buffer); outputStream.write(buffer, 0, count); } inflater.end(); outputStream.close(); byte[] output = outputStream.toByteArray(); if (BuildConfig.DEBUG) AllInOneV2.wtl("CMPRSSN - Original: " + data.length / 1024 + " Kb"); if (BuildConfig.DEBUG) AllInOneV2.wtl("CMPRSSN - Decompressed: " + output.length / 1024 + " Kb"); return output; } catch (Exception e) { e.printStackTrace(); return data; } } }