package com.xda.one.db; import com.xda.one.api.model.interfaces.Forum; import com.xda.one.api.model.response.ResponseForum; import android.app.SearchManager; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.provider.BaseColumns; import android.text.TextUtils; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.xda.one.db.ForumDbHelper.ForumContract.ForumEntry; public class ForumDbHelper extends SQLiteOpenHelper { public static final int DATABASE_VERSION = 3; public static final String DATABASE_NAME = "Forums.db"; public static final String TABLE_NAME = "forumtable"; private static final String SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS " + TABLE_NAME; private static final String TEXT_TYPE = " TEXT"; private static final String INTEGER_TYPE = " INTEGER"; private static final String COMMA_SEP = ","; private static final String UNIQUE = " UNIQUE"; private static final String SQL_CREATE_FORUM_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ForumEntry._ID + INTEGER_TYPE + " PRIMARY KEY" + COMMA_SEP + ForumEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP + ForumEntry.COLUMN_NAME_CONTENT + TEXT_TYPE + COMMA_SEP + ForumEntry.COLUMN_NAME_FORUMID + INTEGER_TYPE + UNIQUE + COMMA_SEP + ForumEntry.COLUMN_NAME_PARENTID + INTEGER_TYPE + COMMA_SEP + ForumEntry.COLUMN_NAME_FORUMSLUG + TEXT_TYPE + COMMA_SEP + ForumEntry.COLUMN_NAME_SUBSCRIBED + INTEGER_TYPE + COMMA_SEP + ForumEntry.COLUMN_NAME_IMAGE + TEXT_TYPE + COMMA_SEP + ForumEntry.COLUMN_NAME_SEARCHABLE + TEXT_TYPE + COMMA_SEP + ForumEntry.COLUMN_NAME_CAN_CONTAIN_THREADS + INTEGER_TYPE + COMMA_SEP + ForumEntry.COLUMN_NAME_WEB_URI + TEXT_TYPE + COMMA_SEP + ForumEntry.COLUMN_NAME_CHILDREN_COUNT + INTEGER_TYPE + " )"; private static ForumDbHelper sForumDbHelper; private ForumDbHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } public static ForumDbHelper getInstance(Context context) { if (sForumDbHelper == null) { sForumDbHelper = new ForumDbHelper(context); } return sForumDbHelper; } private static ContentValues forumToContentValues(final ResponseForum forum) { final ContentValues values = new ContentValues(); values.put(ForumEntry.COLUMN_NAME_TITLE, forum.getTitle()); values.put(ForumEntry.COLUMN_NAME_FORUMID, forum.getForumId()); values.put(ForumEntry.COLUMN_NAME_PARENTID, forum.getParentId()); values.put(ForumEntry.COLUMN_NAME_FORUMSLUG, forum.getForumSlug()); values.put(ForumEntry.COLUMN_NAME_SUBSCRIBED, forum.isSubscribed()); values.put(ForumEntry.COLUMN_NAME_IMAGE, forum.getImageUrl()); values.put(ForumEntry.COLUMN_NAME_SEARCHABLE, forum.getSearchable()); values.put(ForumEntry.COLUMN_NAME_CAN_CONTAIN_THREADS, forum.canContainThreads()); values.put(ForumEntry.COLUMN_NAME_WEB_URI, forum.getWebUri()); values.put(ForumEntry.COLUMN_NAME_CHILDREN_COUNT, forum.getChildren().size()); return values; } public static ResponseForum getForumFromCursor(final Cursor cursor) { return getForumWithTitleFromCursor(cursor, ForumEntry.COLUMN_NAME_TITLE); } public static ResponseForum getSuggestionFromCursor(final Cursor cursor) { return getForumWithTitleFromCursor(cursor, SearchManager.SUGGEST_COLUMN_TEXT_1); } public static ResponseForum getForumWithTitleFromCursor(final Cursor cursor, final String titleColumn) { final ResponseForum forum = new ResponseForum(); forum.setTitle(cursor.getString(cursor.getColumnIndex(titleColumn))); forum.setForumId(cursor.getInt(cursor.getColumnIndex(ForumEntry.COLUMN_NAME_FORUMID))); forum.setParentId(cursor.getInt(cursor.getColumnIndex(ForumEntry.COLUMN_NAME_PARENTID))); forum.setForumSlug(cursor.getString(cursor.getColumnIndex(ForumEntry .COLUMN_NAME_FORUMSLUG))); forum.setSubscribed(cursor.getInt(cursor.getColumnIndex(ForumEntry .COLUMN_NAME_SUBSCRIBED)) != 0); forum.setImageUrl(cursor.getString(cursor.getColumnIndex(ForumEntry.COLUMN_NAME_IMAGE))); forum.setSearchable(cursor.getString(cursor.getColumnIndex(ForumEntry .COLUMN_NAME_SEARCHABLE))); forum.setCanContainThreads(cursor.getInt(cursor.getColumnIndex(ForumEntry .COLUMN_NAME_CAN_CONTAIN_THREADS)) != 0); forum.setWebUri(cursor.getString(cursor.getColumnIndex(ForumEntry.COLUMN_NAME_WEB_URI))); forum.setChildrenCount(cursor.getInt(cursor.getColumnIndex(ForumEntry .COLUMN_NAME_CHILDREN_COUNT))); return forum; } private static Cursor getForumsChildren(final SQLiteDatabase database, final int forumId) { final String whereClause = ForumEntry.COLUMN_NAME_PARENTID + "=" + String.valueOf(forumId); return database.query(ForumDbHelper.TABLE_NAME, null, whereClause, null, null, null, null); } private static void addAllRecursive(final SQLiteDatabase database, final Collection<ResponseForum> list) { if (list == null) { return; } for (final ResponseForum forum : list) { database.insert(TABLE_NAME, null, forumToContentValues(forum)); addAllRecursive(database, forum.getChildren()); } } public static void updateForum(final SQLiteDatabase database, final ResponseForum forum) { final ContentValues values = forumToContentValues(forum); database.replace(TABLE_NAME, null, values); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(SQL_CREATE_FORUM_TABLE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // This database is only a cache for online data, so its upgrade policy is // to simply to discard the data and start over db.execSQL(SQL_DELETE_ENTRIES); onCreate(db); } @Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { onUpgrade(db, oldVersion, newVersion); } public Cursor searchForums(final String query) { if (TextUtils.isEmpty(query)) { return null; } final SQLiteDatabase database = getWritableDatabase(); final String selection = ForumEntry.COLUMN_NAME_SEARCHABLE + " LIKE '%" + query + "%'"; final Map<String, String> hashMap = new HashMap<>(); hashMap.put(ForumEntry._ID, ForumEntry._ID); hashMap.put(ForumEntry.COLUMN_NAME_TITLE, ForumEntry.COLUMN_NAME_TITLE + " as " + SearchManager.SUGGEST_COLUMN_TEXT_1); hashMap.put(ForumEntry.COLUMN_NAME_CONTENT, ForumEntry.COLUMN_NAME_CONTENT); hashMap.put(ForumEntry.COLUMN_NAME_FORUMID, ForumEntry.COLUMN_NAME_FORUMID); hashMap.put(ForumEntry.COLUMN_NAME_PARENTID, ForumEntry.COLUMN_NAME_PARENTID); hashMap.put(ForumEntry.COLUMN_NAME_FORUMSLUG, ForumEntry.COLUMN_NAME_FORUMSLUG); hashMap.put(ForumEntry.COLUMN_NAME_SUBSCRIBED, ForumEntry.COLUMN_NAME_SUBSCRIBED); hashMap.put(ForumEntry.COLUMN_NAME_IMAGE, ForumEntry.COLUMN_NAME_IMAGE); hashMap.put(ForumEntry.COLUMN_NAME_SEARCHABLE, ForumEntry.COLUMN_NAME_SEARCHABLE); hashMap.put(ForumEntry.COLUMN_NAME_CAN_CONTAIN_THREADS, ForumEntry.COLUMN_NAME_CAN_CONTAIN_THREADS); hashMap.put(ForumEntry.COLUMN_NAME_WEB_URI, ForumEntry.COLUMN_NAME_WEB_URI); hashMap.put(ForumEntry.COLUMN_NAME_CHILDREN_COUNT, ForumEntry.COLUMN_NAME_CHILDREN_COUNT); final SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); builder.setProjectionMap(hashMap); builder.setTables(TABLE_NAME); return builder.query(database, null, selection, null, null, null, null); } public void addAllRecursive(final Collection<ResponseForum> list) { final SQLiteDatabase database = getWritableDatabase(); database.beginTransaction(); try { addAllRecursive(database, list); database.setTransactionSuccessful(); } finally { database.endTransaction(); } } public void replaceRawForumResponse(final List<ResponseForum> list) { final SQLiteDatabase database = getWritableDatabase(); database.delete(TABLE_NAME, null, null); addAllRecursive(list); } public List<ResponseForum> getTopLevelForums() { return getForumChildren(-1); } public List<ResponseForum> getForumChildren(final int forumId) { final SQLiteDatabase database = getWritableDatabase(); final List<ResponseForum> forums = new ArrayList<>(); final Cursor cursor = getForumsChildren(database, forumId); if (cursor.getCount() > 0) { cursor.moveToFirst(); while (!cursor.isAfterLast()) { final ResponseForum forum = getForumFromCursor(cursor); forums.add(forum); cursor.moveToNext(); } } cursor.close(); return forums; } public void updateSubscribedFlag(final Forum forum, final boolean newSubscribedValue) { final SQLiteDatabase database = getWritableDatabase(); final ContentValues contentValues = new ContentValues(); contentValues.put(ForumEntry.COLUMN_NAME_SUBSCRIBED, newSubscribedValue); database.update(TABLE_NAME, contentValues, ForumEntry.COLUMN_NAME_FORUMID + "=" + forum .getForumId(), null); } public void updateForumCollection(final Collection<ResponseForum> list) { final SQLiteDatabase database = getWritableDatabase(); database.beginTransaction(); try { for (final ResponseForum responseForum : list) { updateForum(database, responseForum); } database.setTransactionSuccessful(); } finally { database.endTransaction(); } } public Forum searchSlug(final int parentId, final String slug) { final SQLiteDatabase database = getWritableDatabase(); final String selection = String.format("%s = '%s' AND %s = %d", ForumEntry.COLUMN_NAME_FORUMSLUG, slug, ForumEntry.COLUMN_NAME_PARENTID, parentId); final Cursor cursor = database.query(TABLE_NAME, null, selection, null, null, null, null); if (cursor.getCount() > 0) { cursor.moveToFirst(); return getForumFromCursor(cursor); } return null; } public static final class ForumContract { // To prevent someone from accidentally instantiating the contract class, // give it an empty constructor. private ForumContract() { } /* Inner class that defines the table contents */ public static abstract class ForumEntry implements BaseColumns { public static final String COLUMN_NAME_TITLE = "title"; public static final String COLUMN_NAME_CONTENT = "content"; public static final String COLUMN_NAME_FORUMID = "forumid"; public static final String COLUMN_NAME_PARENTID = "parentid"; public static final String COLUMN_NAME_FORUMSLUG = "forumslug"; public static final String COLUMN_NAME_SUBSCRIBED = "subscribed"; public static final String COLUMN_NAME_IMAGE = "image"; public static final String COLUMN_NAME_SEARCHABLE = "searchable"; public static final String COLUMN_NAME_CAN_CONTAIN_THREADS = "can_contain_threads"; public static final String COLUMN_NAME_WEB_URI = "web_uri"; public static final String COLUMN_NAME_CHILDREN_COUNT = "children_count"; } } }