| 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; |
| } |
| } |