package com.lateensoft.pathfinder.toolkit.db.dao; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.lateensoft.pathfinder.toolkit.dao.DataAccessException; import com.lateensoft.pathfinder.toolkit.dao.GenericDAO; import com.lateensoft.pathfinder.toolkit.db.CursorUtil; import com.lateensoft.pathfinder.toolkit.db.Database; import org.jetbrains.annotations.Nullable; import roboguice.RoboGuice; import java.util.Hashtable; import java.util.List; public abstract class GenericTableDAO<RowId, Entity, RowData> implements GenericDAO<Entity> { private Database database; private Table table; public GenericTableDAO(Context context) { database = RoboGuice.getInjector(context).getInstance(Database.class); table = initTable(); } protected abstract Table initTable(); public Entity find(RowId id) { String selector = andSelectors(getIdSelector(id), getBaseSelector()); String tables = getFromQueryClause(); String[] columns = getColumnsForQuery(); Cursor cursor = database.query(tables, columns, selector); cursor.moveToFirst(); if (!cursor.isAfterLast()) { Hashtable<String, Object> hashTable = CursorUtil.getTableOfValues(cursor); return buildFromHashTable(hashTable); } else { return null; } } protected List<String> getTablesForQuery() { return Lists.newArrayList(getTable().getName()); } protected String getFromQueryClause() { return Joiner.on(", ").join(getTablesForQuery()); } protected String[] getColumnsForQuery() { return getTable().getColumnNames(); } public boolean exists(RowId id) { Cursor cursor= getDatabase().rawQuery("select count(*) count from " + getTable().getName() + " where " + getIdSelector(id), null); cursor.moveToFirst(); int count = cursor.getInt(cursor.getColumnIndex("count")); cursor.close(); return count != 0; } @Override public List<Entity> findAll() { return findFiltered(getBaseSelector(), getDefaultOrderBy()); } public List<Entity> findFiltered(String selector, String orderBy) { String table = getFromQueryClause(); String[] columns = getColumnsForQuery(); return findFiltered(table, columns, selector, orderBy); } public List<Entity> findFiltered(String tables, String[] columns, String selector, String orderBy) { Cursor cursor = database.query(true, tables, columns, selector, null, null, null, orderBy, null); List<Entity> entities = Lists.newArrayListWithCapacity(cursor.getCount()); cursor.moveToFirst(); while (!cursor.isAfterLast()) { Hashtable<String, Object> hashTable = CursorUtil.getTableOfValues(cursor); entities.add(buildFromHashTable(hashTable)); cursor.moveToNext(); } return entities; } public void remove(RowData rowData) throws DataAccessException { removeById(getIdFromRowData(rowData)); } public void removeById(RowId id) throws DataAccessException { String selector = getIdSelector(id); String table = getTable().getName(); int returnVal = database.delete(table, selector); if (returnVal <= 0) { throw new DataAccessException("Database.delete for " + id + " returned " + returnVal); } } public RowId add(RowData rowData) throws DataAccessException { try { beginTransaction(); ContentValues values = getContentValues(rowData); String table = getTable().getName(); long id = getDatabase().insert(table, values); if (id == -1) { throw new DataAccessException("Failed to insert " + rowData); } if (!isIdSet(rowData)) { setId(rowData, id); } setTransactionSuccessful(); } finally { endTransaction(); } return getIdFromRowData(rowData); } protected void beginTransaction() { database.beginTransaction(); } protected void setTransactionSuccessful() { database.setTransactionSuccessful(); } protected void endTransaction() { database.endTransaction(); } protected abstract boolean isIdSet(RowData entity); protected abstract void setId(RowData entity, long id); public void update(RowData rowData) throws DataAccessException { try { beginTransaction(); String selector = getIdSelector(getIdFromRowData(rowData)); ContentValues values = getContentValues(rowData); String table = getTable().getName(); int returnVal = getDatabase().update(table, values, selector); if (returnVal <= 0) { throw new DataAccessException("Failed to update (code " + returnVal + ") " + rowData); } setTransactionSuccessful(); } finally { endTransaction(); } } protected abstract RowId getIdFromRowData(RowData rowData); protected abstract ContentValues getContentValues(RowData rowData); protected abstract String getIdSelector(RowId id); protected abstract Entity buildFromHashTable(Hashtable<String, Object> hashTable); protected @Nullable String getBaseSelector() { return null; } protected String getDefaultOrderBy() { return null; } protected Database getDatabase() { return database; } public Table getTable() { return table; } public static String andSelectors(String... selectors) { String selector = Joiner.on(" AND ").skipNulls().join(selectors); if (!selector.isEmpty()) { return selector; } else { return null; } } }