package org.wordpress.android.datasets; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteStatement; import org.wordpress.android.models.ReaderComment; import org.wordpress.android.models.ReaderCommentList; import org.wordpress.android.models.ReaderPost; import org.wordpress.android.util.SqlUtils; /** * stores comments on reader posts */ public class ReaderCommentTable { private static final String COLUMN_NAMES = " blog_id," + " post_id," + " comment_id," + " parent_id," + " author_name," + " author_avatar," + " author_url," + " author_id," + " author_blog_id," + " published," + " timestamp," + " status," + " text," + " num_likes," + " is_liked," + " page_number"; protected static void createTables(SQLiteDatabase db) { db.execSQL("CREATE TABLE tbl_comments (" + " blog_id INTEGER DEFAULT 0," + " post_id INTEGER DEFAULT 0," + " comment_id INTEGER DEFAULT 0," + " parent_id INTEGER DEFAULT 0," + " author_name TEXT," + " author_avatar TEXT," + " author_url TEXT," + " author_id INTEGER DEFAULT 0," + " author_blog_id INTEGER DEFAULT 0," + " published TEXT," + " timestamp INTEGER DEFAULT 0," + " status TEXT," + " text TEXT," + " num_likes INTEGER DEFAULT 0," + " is_liked INTEGER DEFAULT 0," + " page_number INTEGER DEFAULT 0," + " PRIMARY KEY (blog_id, post_id, comment_id))"); db.execSQL("CREATE INDEX idx_page_number ON tbl_comments(page_number)"); } protected static void dropTables(SQLiteDatabase db) { db.execSQL("DROP TABLE IF EXISTS tbl_comments"); } protected static void reset(SQLiteDatabase db) { dropTables(db); createTables(db); } protected static int purge(SQLiteDatabase db) { // purge comments attached to posts that no longer exist int numDeleted = db.delete("tbl_comments", "post_id NOT IN (SELECT DISTINCT post_id FROM tbl_posts)", null); // purge all but the first page of comments numDeleted += db.delete("tbl_comments", "page_number != 1", null); return numDeleted; } public static boolean isEmpty() { return (getNumComments()==0); } private static int getNumComments() { long count = SqlUtils.getRowCount(ReaderDatabase.getReadableDb(), "tbl_comments"); return (int)count; } /* * returns the highest page_number for comments on the passed post */ public static int getLastPageNumberForPost(long blogId, long postId) { String[] args = {Long.toString(blogId), Long.toString(postId)}; return SqlUtils.intForQuery(ReaderDatabase.getReadableDb(), "SELECT MAX(page_number) FROM tbl_comments WHERE blog_id=? AND post_id=?", args); } /* * returns the page number for a specific comment */ public static int getPageNumberForComment(long blogId, long postId, long commentId) { String[] args = {Long.toString(blogId), Long.toString(postId), Long.toString(commentId)}; return SqlUtils.intForQuery(ReaderDatabase.getReadableDb(), "SELECT page_number FROM tbl_comments WHERE blog_id=? AND post_id=? AND comment_id=?", args); } /* * removes all comments for the passed post */ public static void purgeCommentsForPost(long blogId, long postId) { String[] args = {Long.toString(blogId), Long.toString(postId)}; ReaderDatabase.getWritableDb().delete("tbl_comments", "blog_id=? AND post_id=?", args); } /* * returns the #comments stored locally for this post, which may differ from ReaderPostTable.getNumCommentsOnPost * (which is the #comments the server says exist for this post) */ public static int getNumCommentsForPost(ReaderPost post) { if (post == null) { return 0; } return getNumCommentsForPost(post.blogId, post.postId); } private static int getNumCommentsForPost(long blogId, long postId) { String[] args = {Long.toString(blogId), Long.toString(postId)}; return SqlUtils.intForQuery(ReaderDatabase.getReadableDb(), "SELECT count(*) FROM tbl_comments WHERE blog_id=? AND post_id=?", args); } public static ReaderCommentList getCommentsForPost(ReaderPost post) { if (post == null) { return new ReaderCommentList(); } String[] args = {Long.toString(post.blogId), Long.toString(post.postId)}; Cursor c = ReaderDatabase.getReadableDb().rawQuery("SELECT * FROM tbl_comments WHERE blog_id=? AND post_id=? ORDER BY timestamp", args); try { ReaderCommentList comments = new ReaderCommentList(); if (c.moveToFirst()) { do { comments.add(getCommentFromCursor(c)); } while (c.moveToNext()); } return comments; } finally { SqlUtils.closeCursor(c); } } public static void addOrUpdateComment(ReaderComment comment) { if (comment == null) { return; } ReaderCommentList comments = new ReaderCommentList(); comments.add(comment); addOrUpdateComments(comments); } public static void addOrUpdateComments(ReaderCommentList comments) { if (comments == null || comments.size() == 0) { return; } SQLiteDatabase db = ReaderDatabase.getWritableDb(); db.beginTransaction(); SQLiteStatement stmt = db.compileStatement("INSERT OR REPLACE INTO tbl_comments (" + COLUMN_NAMES + ") VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12,?13,?14,?15,?16)"); try { for (ReaderComment comment: comments) { stmt.bindLong (1, comment.blogId); stmt.bindLong (2, comment.postId); stmt.bindLong (3, comment.commentId); stmt.bindLong (4, comment.parentId); stmt.bindString(5, comment.getAuthorName()); stmt.bindString(6, comment.getAuthorAvatar()); stmt.bindString(7, comment.getAuthorUrl()); stmt.bindLong (8, comment.authorId); stmt.bindLong (9, comment.authorBlogId); stmt.bindString(10, comment.getPublished()); stmt.bindLong (11, comment.timestamp); stmt.bindString(12, comment.getStatus()); stmt.bindString(13, comment.getText()); stmt.bindLong (14, comment.numLikes); stmt.bindLong (15, SqlUtils.boolToSql(comment.isLikedByCurrentUser)); stmt.bindLong (16, comment.pageNumber); stmt.execute(); } db.setTransactionSuccessful(); } finally { db.endTransaction(); SqlUtils.closeStatement(stmt); } } public static ReaderComment getComment(long blogId, long postId, long commentId) { String[] args = new String[] {Long.toString(blogId), Long.toString(postId), Long.toString(commentId)}; Cursor c = ReaderDatabase.getReadableDb().rawQuery( "SELECT * FROM tbl_comments WHERE blog_id=? AND post_id=? AND comment_id=? LIMIT 1", args); try { if (!c.moveToFirst()) { return null; } return getCommentFromCursor(c); } finally { SqlUtils.closeCursor(c); } } public static void deleteComment(ReaderPost post, long commentId) { if (post == null) { return; } String[] args = {Long.toString(post.blogId), Long.toString(post.postId), Long.toString(commentId)}; ReaderDatabase.getWritableDb().delete("tbl_comments", "blog_id=? AND post_id=? AND comment_id=?", args); } /* * returns true if any of the passed comments don't already exist * IMPORTANT: assumes passed comments are all for the same post */ public static boolean hasNewComments(ReaderCommentList comments) { if (comments == null || comments.size() == 0) { return false; } StringBuilder sb = new StringBuilder( "SELECT COUNT(*) FROM tbl_comments WHERE blog_id=? AND post_id=? AND comment_id IN ("); boolean isFirst = true; for (ReaderComment comment: comments) { if (isFirst) { isFirst = false; } else { sb.append(","); } sb.append(comment.commentId); } sb.append(")"); String[] args = {Long.toString(comments.get(0).blogId), Long.toString(comments.get(0).postId)}; int numExisting = SqlUtils.intForQuery(ReaderDatabase.getReadableDb(), sb.toString(), args); return numExisting != comments.size(); } /* * returns the #likes known to exist for this comment */ public static int getNumLikesForComment(long blogId, long postId, long commentId) { String[] args = {Long.toString(blogId), Long.toString(postId), Long.toString(commentId)}; return SqlUtils.intForQuery(ReaderDatabase.getReadableDb(), "SELECT num_likes FROM tbl_comments WHERE blog_id=? AND post_id=? AND comment_id=?", args); } /* * updates both the like count for a comment and whether it's liked by the current user */ public static void setLikesForComment(ReaderComment comment, int numLikes, boolean isLikedByCurrentUser) { if (comment == null) { return; } String[] args = {Long.toString(comment.blogId), Long.toString(comment.postId), Long.toString(comment.commentId)}; ContentValues values = new ContentValues(); values.put("num_likes", numLikes); values.put("is_liked", SqlUtils.boolToSql(isLikedByCurrentUser)); ReaderDatabase.getWritableDb().update( "tbl_comments", values, "blog_id=? AND post_id=? AND comment_id=?", args); } public static boolean isCommentLikedByCurrentUser(ReaderComment comment) { if (comment == null) { return false; } return isCommentLikedByCurrentUser(comment.blogId, comment.postId, comment.commentId); } public static boolean isCommentLikedByCurrentUser(long blogId, long postId, long commentId) { String[] args = {Long.toString(blogId), Long.toString(postId), Long.toString(commentId)}; return SqlUtils.boolForQuery(ReaderDatabase.getReadableDb(), "SELECT is_liked FROM tbl_comments WHERE blog_id=? AND post_id=? and comment_id=?", args); } public static boolean commentExists(long blogId, long postId, long commentId) { String[] args = {Long.toString(blogId), Long.toString(postId), Long.toString(commentId)}; return SqlUtils.boolForQuery(ReaderDatabase.getReadableDb(), "SELECT 1 FROM tbl_comments WHERE blog_id=? AND post_id=? AND comment_id=?", args); } private static ReaderComment getCommentFromCursor(Cursor c) { if (c == null) { throw new IllegalArgumentException("null comment cursor"); } ReaderComment comment = new ReaderComment(); comment.commentId = c.getLong(c.getColumnIndex("comment_id")); comment.blogId = c.getLong(c.getColumnIndex("blog_id")); comment.postId = c.getLong(c.getColumnIndex("post_id")); comment.parentId = c.getLong(c.getColumnIndex("parent_id")); comment.setPublished(c.getString(c.getColumnIndex("published"))); comment.timestamp = c.getLong(c.getColumnIndex("timestamp")); comment.setAuthorAvatar(c.getString(c.getColumnIndex("author_avatar"))); comment.setAuthorName(c.getString(c.getColumnIndex("author_name"))); comment.setAuthorUrl(c.getString(c.getColumnIndex("author_url"))); comment.authorId = c.getLong(c.getColumnIndex("author_id")); comment.authorBlogId = c.getLong(c.getColumnIndex("author_blog_id")); comment.setStatus(c.getString(c.getColumnIndex("status"))); comment.setText(c.getString(c.getColumnIndex("text"))); comment.numLikes = c.getInt(c.getColumnIndex("num_likes")); comment.isLikedByCurrentUser = SqlUtils.sqlToBool(c.getInt(c.getColumnIndex("is_liked"))); comment.pageNumber = c.getInt(c.getColumnIndex("page_number")); return comment; } }