diff options
Diffstat (limited to 'WordPress/src/main/java/org/wordpress/android/datasets/PeopleTable.java')
-rw-r--r-- | WordPress/src/main/java/org/wordpress/android/datasets/PeopleTable.java | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/WordPress/src/main/java/org/wordpress/android/datasets/PeopleTable.java b/WordPress/src/main/java/org/wordpress/android/datasets/PeopleTable.java new file mode 100644 index 000000000..84ac02dba --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/datasets/PeopleTable.java @@ -0,0 +1,354 @@ +package org.wordpress.android.datasets; + +import android.content.ContentValues; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteQueryBuilder; +import android.support.annotation.Nullable; + +import org.wordpress.android.WordPress; +import org.wordpress.android.models.Person; +import org.wordpress.android.models.Role; +import org.wordpress.android.ui.people.utils.PeopleUtils; +import org.wordpress.android.util.AppLog; +import org.wordpress.android.util.SqlUtils; + +import java.util.ArrayList; +import java.util.List; + +public class PeopleTable { + private static final String TEAM_TABLE = "people_team"; + private static final String FOLLOWERS_TABLE = "people_followers"; + private static final String EMAIL_FOLLOWERS_TABLE = "people_email_followers"; + private static final String VIEWERS_TABLE = "people_viewers"; + + private static SQLiteDatabase getReadableDb() { + return WordPress.wpDB.getDatabase(); + } + private static SQLiteDatabase getWritableDb() { + return WordPress.wpDB.getDatabase(); + } + + public static void createTables(SQLiteDatabase db) { + db.execSQL("CREATE TABLE " + TEAM_TABLE + " (" + + "person_id INTEGER DEFAULT 0," + + "local_blog_id INTEGER DEFAULT 0," + + "user_name TEXT," + + "display_name TEXT," + + "avatar_url TEXT," + + "role TEXT," + + "PRIMARY KEY (person_id, local_blog_id)" + + ");"); + + db.execSQL("CREATE TABLE " + FOLLOWERS_TABLE + " (" + + "person_id INTEGER DEFAULT 0," + + "local_blog_id INTEGER DEFAULT 0," + + "user_name TEXT," + + "display_name TEXT," + + "avatar_url TEXT," + + "subscribed TEXT," + + "PRIMARY KEY (person_id, local_blog_id)" + + ");"); + + db.execSQL("CREATE TABLE " + EMAIL_FOLLOWERS_TABLE + " (" + + "person_id INTEGER DEFAULT 0," + + "local_blog_id INTEGER DEFAULT 0," + + "display_name TEXT," + + "avatar_url TEXT," + + "subscribed TEXT," + + "PRIMARY KEY (person_id, local_blog_id)" + + ");"); + } + + public static void createViewersTable(SQLiteDatabase db) { + db.execSQL("CREATE TABLE " + VIEWERS_TABLE + " (" + + "person_id INTEGER DEFAULT 0," + + "local_blog_id INTEGER DEFAULT 0," + + "user_name TEXT," + + "display_name TEXT," + + "avatar_url TEXT," + + "PRIMARY KEY (person_id, local_blog_id)" + + ");"); + } + + private static void dropTables(SQLiteDatabase db) { + // People table is not used anymore, each filter now has it's own table + db.execSQL("DROP TABLE IF EXISTS people"); + + db.execSQL("DROP TABLE IF EXISTS " + TEAM_TABLE); + db.execSQL("DROP TABLE IF EXISTS " + FOLLOWERS_TABLE); + db.execSQL("DROP TABLE IF EXISTS " + EMAIL_FOLLOWERS_TABLE); + db.execSQL("DROP TABLE IF EXISTS " + VIEWERS_TABLE); + } + + public static void reset(SQLiteDatabase db) { + AppLog.i(AppLog.T.PEOPLE, "resetting people table"); + dropTables(db); + createTables(db); + } + + public static void saveUser(Person person) { + save(TEAM_TABLE, person, getWritableDb()); + } + + private static void save(String table, Person person, SQLiteDatabase database) { + ContentValues values = new ContentValues(); + values.put("person_id", person.getPersonID()); + values.put("local_blog_id", person.getLocalTableBlogId()); + values.put("display_name", person.getDisplayName()); + values.put("avatar_url", person.getAvatarUrl()); + + switch (table) { + case TEAM_TABLE: + values.put("user_name", person.getUsername()); + if (person.getRole() != null) { + values.put("role", person.getRole().toString()); + } + break; + case FOLLOWERS_TABLE: + values.put("user_name", person.getUsername()); + values.put("subscribed", person.getSubscribed()); + break; + case EMAIL_FOLLOWERS_TABLE: + values.put("subscribed", person.getSubscribed()); + break; + case VIEWERS_TABLE: + values.put("user_name", person.getUsername()); + break; + } + + database.insertWithOnConflict(table, null, values, SQLiteDatabase.CONFLICT_REPLACE); + } + + public static void saveUsers(List<Person> peopleList, int localTableBlogId, boolean isFreshList) { + savePeople(TEAM_TABLE, peopleList, localTableBlogId, isFreshList); + } + + public static void saveFollowers(List<Person> peopleList, int localTableBlogId, boolean isFreshList) { + savePeople(FOLLOWERS_TABLE, peopleList, localTableBlogId, isFreshList); + } + + public static void saveEmailFollowers(List<Person> peopleList, int localTableBlogId, boolean isFreshList) { + savePeople(EMAIL_FOLLOWERS_TABLE, peopleList, localTableBlogId, isFreshList); + } + + public static void saveViewers(List<Person> peopleList, int localTableBlogId, boolean isFreshList) { + savePeople(VIEWERS_TABLE, peopleList, localTableBlogId, isFreshList); + } + + private static void savePeople(String table, List<Person> peopleList, int localTableBlogId, boolean isFreshList) { + getWritableDb().beginTransaction(); + try { + // We have a fresh list, remove the previous list of people in case it was deleted on remote + if (isFreshList) { + PeopleTable.deletePeople(table, localTableBlogId); + } + + for (Person person : peopleList) { + PeopleTable.save(table, person, getWritableDb()); + } + getWritableDb().setTransactionSuccessful(); + } finally { + getWritableDb().endTransaction(); + } + } + + public static void deletePeopleForLocalBlogId(int localTableBlogId) { + deletePeople(TEAM_TABLE, localTableBlogId); + deletePeople(FOLLOWERS_TABLE, localTableBlogId); + deletePeople(EMAIL_FOLLOWERS_TABLE, localTableBlogId); + deletePeople(VIEWERS_TABLE, localTableBlogId); + } + + private static void deletePeople(String table, int localTableBlogId) { + String[] args = new String[]{Integer.toString(localTableBlogId)}; + getWritableDb().delete(table, "local_blog_id=?1", args); + } + + /** + * In order to avoid syncing issues, this method will be called when People page is created. We only keep + * the first page of users, so we don't show an empty screen. When fresh data is received, it'll replace + * the existing page. + * @param localTableBlogId - the local blog id people will be deleted from + */ + public static void deletePeopleExceptForFirstPage(int localTableBlogId) { + int fetchLimit = PeopleUtils.FETCH_LIMIT; + String[] tables = {TEAM_TABLE, FOLLOWERS_TABLE, EMAIL_FOLLOWERS_TABLE, VIEWERS_TABLE}; + + getWritableDb().beginTransaction(); + try { + for (String table : tables) { + int size = getPeopleCountForLocalBlogId(table, localTableBlogId); + if (size > fetchLimit) { + String where = "local_blog_id=" + localTableBlogId; + String[] columns = {"person_id"}; + String limit = Integer.toString(size - fetchLimit); + String orderBy; + if (shouldOrderAlphabetically(table)) { + orderBy = "lower(display_name) DESC, lower(user_name) DESC"; + } else { + orderBy = "ROWID DESC"; + } + String inQuery = SQLiteQueryBuilder.buildQueryString(false, table, columns, where, null, null, + orderBy, limit); + + String[] args = new String[] {Integer.toString(localTableBlogId)}; + getWritableDb().delete(table, "local_blog_id=?1 AND person_id IN (" + inQuery + ")", args); + } + } + getWritableDb().setTransactionSuccessful(); + } finally { + getWritableDb().endTransaction(); + } + } + + public static int getUsersCountForLocalBlogId(int localTableBlogId) { + return getPeopleCountForLocalBlogId(TEAM_TABLE, localTableBlogId); + } + + public static int getViewersCountForLocalBlogId(int localTableBlogId) { + return getPeopleCountForLocalBlogId(VIEWERS_TABLE, localTableBlogId); + } + + private static int getPeopleCountForLocalBlogId(String table, int localTableBlogId) { + String[] args = new String[]{Integer.toString(localTableBlogId)}; + String sql = "SELECT COUNT(*) FROM " + table + " WHERE local_blog_id=?"; + return SqlUtils.intForQuery(getReadableDb(), sql, args); + } + + public static void deletePerson(long personID, int localTableBlogId, Person.PersonType personType) { + String table = getTableForPersonType(personType); + if (table != null) { + deletePerson(table, personID, localTableBlogId); + } + } + + private static void deletePerson(String table, long personID, int localTableBlogId) { + String[] args = new String[]{Long.toString(personID), Integer.toString(localTableBlogId)}; + getWritableDb().delete(table, "person_id=? AND local_blog_id=?", args); + } + + public static List<Person> getUsers(int localTableBlogId) { + return PeopleTable.getPeople(TEAM_TABLE, localTableBlogId); + } + + public static List<Person> getFollowers(int localTableBlogId) { + return PeopleTable.getPeople(FOLLOWERS_TABLE, localTableBlogId); + } + + public static List<Person> getEmailFollowers(int localTableBlogId) { + return PeopleTable.getPeople(EMAIL_FOLLOWERS_TABLE, localTableBlogId); + } + + public static List<Person> getViewers(int localTableBlogId) { + return PeopleTable.getPeople(VIEWERS_TABLE, localTableBlogId); + } + + private static List<Person> getPeople(String table, int localTableBlogId) { + String[] args = {Integer.toString(localTableBlogId)}; + String orderBy; + if (shouldOrderAlphabetically(table)) { + orderBy = " ORDER BY lower(display_name), lower(user_name)"; + } else { + // we want the server-side order for followers & viewers + orderBy = " ORDER BY ROWID"; + } + Cursor c = getReadableDb().rawQuery("SELECT * FROM " + table + " WHERE local_blog_id=?" + orderBy, args); + + List<Person> people = new ArrayList<>(); + try { + while (c.moveToNext()) { + Person person = getPersonFromCursor(c, table, localTableBlogId); + people.add(person); + } + } finally { + SqlUtils.closeCursor(c); + } + return people; + } + + @Nullable + public static Person getPerson(long personId, int localTableBlogId, Person.PersonType personType) { + String table = getTableForPersonType(personType); + if (table != null) { + return getPerson(table, personId, localTableBlogId); + } + return null; + } + + public static Person getUser(long personId, int localTableBlogId) { + return getPerson(TEAM_TABLE, personId, localTableBlogId); + } + + /** + * retrieve a person + * @param table - sql table the person record is in + * @param personId - id of a person in a particular blog + * @param localTableBlogId - the local blog id the user belongs to + * @return Person if found, null otherwise + */ + private static Person getPerson(String table, long personId, int localTableBlogId) { + String[] args = { Long.toString(personId), Integer.toString(localTableBlogId)}; + Cursor c = getReadableDb().rawQuery("SELECT * FROM " + table + + " WHERE person_id=? AND local_blog_id=?", args); + try { + if (!c.moveToFirst()) { + return null; + } + return getPersonFromCursor(c, table, localTableBlogId); + } finally { + SqlUtils.closeCursor(c); + } + } + + private static Person getPersonFromCursor(Cursor c, String table, int localTableBlogId) { + long personId = c.getInt(c.getColumnIndex("person_id")); + + Person person = new Person(personId, localTableBlogId); + person.setDisplayName(c.getString(c.getColumnIndex("display_name"))); + person.setAvatarUrl(c.getString(c.getColumnIndex("avatar_url"))); + switch (table) { + case TEAM_TABLE: + person.setUsername(c.getString(c.getColumnIndex("user_name"))); + String role = c.getString(c.getColumnIndex("role")); + person.setRole(Role.fromString(role)); + person.setPersonType(Person.PersonType.USER); + break; + case FOLLOWERS_TABLE: + person.setUsername(c.getString(c.getColumnIndex("user_name"))); + person.setSubscribed(c.getString(c.getColumnIndex("subscribed"))); + person.setPersonType(Person.PersonType.FOLLOWER); + break; + case EMAIL_FOLLOWERS_TABLE: + person.setSubscribed(c.getString(c.getColumnIndex("subscribed"))); + person.setPersonType(Person.PersonType.EMAIL_FOLLOWER); + break; + case VIEWERS_TABLE: + person.setUsername(c.getString(c.getColumnIndex("user_name"))); + person.setPersonType(Person.PersonType.VIEWER); + break; + } + + return person; + } + + // order is disabled for followers & viewers for now since the API is not supporting it + private static boolean shouldOrderAlphabetically(String table) { + return table.equals(TEAM_TABLE); + } + + @Nullable + private static String getTableForPersonType(Person.PersonType personType) { + switch (personType) { + case USER: + return TEAM_TABLE; + case FOLLOWER: + return FOLLOWERS_TABLE; + case EMAIL_FOLLOWER: + return EMAIL_FOLLOWERS_TABLE; + case VIEWER: + return VIEWERS_TABLE; + } + return null; + } +} |