package com.airlocksoftware.hackernews.model; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.StringUtils; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import com.airlocksoftware.database.SqlObject; import com.airlocksoftware.hackernews.activity.LoginActivity; import com.airlocksoftware.hackernews.activity.LoginActivity.PostAction; import com.airlocksoftware.hackernews.cache.DbHelperSingleton; import com.airlocksoftware.hackernews.data.UserPrefs; import com.airlocksoftware.hackernews.loader.AsyncVotingService; @SuppressWarnings("serial") /** Encapsulates data about a Story (e.g. articles on the front page). Since it's extending SqlObject, any public, non-static, * non-transient field is cached in the database**/ public class Story extends SqlObject { public long storyId; public int position; public String whence; public String url; public String title; public String domain; public int numPoints; public String username; public int numComments; public String ago; public String selfText; public boolean isUpvoted; // data used for caching purposes public String auth; public Page page; // is the Story archived (i.e. can't reply or comment) public boolean isArchived = false; // by default // constant values need to match field names above public static final String STORY_ID = "storyId"; public static final String POSITION = "position"; public static final String WHENCE = "go_to"; public static final String URL = "url"; public static final String TITLE = "title"; public static final String DOMAIN = "domain"; public static final String NUM_POINTS = "numPoints"; public static final String USERNAME = "username"; public static final String NUM_COMMENTS = "numComments"; public static final String AGO = "ago"; public static final String SELF_TEXT = "selfText"; public static final String IS_UPVOTED = "isUpvoted"; public static final String AUTH = "auth"; public static final String PAGE = "page"; public static final String IS_ARCHIVED = "isArchived"; @Override public String toString() { String toReturn = ""; toReturn += "postition: " + position; toReturn += "\nstoryId: " + storyId; if (whence != null) toReturn += "\ngo_to: " + whence; if (url != null) toReturn += "\nurl: " + url; if (title != null) toReturn += "\ntitle: " + title; if (domain != null) toReturn += "\ndomain: " + domain; toReturn += "\npoints: " + numPoints; if (username != null) toReturn += "\nuser: " + username; toReturn += "\ncomments: " + numComments; if (ago != null) toReturn += "\nago: " + ago; if (auth != null) toReturn += "\nauth: " + auth; if (selfText != null && !selfText.equals("")) { toReturn += "\nselfText: " + "yes"; } { toReturn += "\nselfText: " + "no"; } return toReturn; } public boolean upvote(Context context) { UserPrefs data = new UserPrefs(context); if (data.isLoggedIn()) { // create the vote and save it to database Vote vote = new Vote(); vote.auth = auth; vote.username = data.getUsername(); vote.whence = whence; vote.itemId = storyId; SQLiteDatabase db = DbHelperSingleton.getInstance(context) .getWritableDatabase(); vote.create(db); // update comments upvote status isUpvoted = true; update(db); // run async voting service AsyncVotingService service = new AsyncVotingService(context); service.execute(); return true; } else { Intent intent = new Intent(context, LoginActivity.class); intent.putExtra(LoginActivity.POST_ACTION, PostAction.UPVOTE); intent.putExtra(LoginActivity.POST_STORY, this); context.startActivity(intent); return false; } } public boolean create(SQLiteDatabase db) { return super.createAndGenerateId(db); } public static Story cachedById(SQLiteDatabase db, long sId) { Story story = new Story(); Cursor c = db.query(story.getTableName(), story.getColNames(), STORY_ID + "=?", new String[] { Long.toString(sId) }, null, null, null); if (c.moveToFirst()) { story.readFromCursor(c); c.close(); return story; } else { c.close(); return null; } } /** Gets stories linked to this page from the cache **/ public static List<Story> cachedByPage(SQLiteDatabase db, Page Page) { Story firstStory = new Story(); List<Story> stories = new ArrayList<Story>(); Cursor c = db.query(firstStory.getTableName(), firstStory.getColNames(), PAGE + "=?", new String[] { Page.toString() }, null, null, null); if (c.moveToFirst()) { firstStory.readFromCursor(c); stories.add(firstStory); c.moveToNext(); for (int i = 1; i < c.getCount(); i++) { Story story = new Story(); story.readFromCursor(c); stories.add(story); c.moveToNext(); } } c.close(); return stories; } /** Deletes any cached rows matching page **/ public static void clearCache(SQLiteDatabase db, Page page) { Story story = new Story(); db.delete(story.getTableName(), PAGE + "=?", new String[] { page.toString() }); } /** Adds these values to the cache, copying over replyFnid & commentsTimestamp **/ public static void cacheValues(SQLiteDatabase db, List<Story> stories) { for (Story story : stories) { story.create(db); } } /** Checks the story for attributes which indicate it is a YCombinator job post & doesn't have a comments page. **/ public static boolean isYCombinatorJobPost(Story story) { boolean isJobPost = story != null && StringUtils.isNotBlank(story.title) && StringUtils.isNotBlank(story.url) && story.storyId == 0; // TODO this is optional if the above doesn't work well // isJobPost = isJobPost && StringUtils.isBlank(story.username) && StringUtils.isBlank(story.ago); return isJobPost; } }