diff --git a/app/build.gradle b/app/build.gradle index 726d6f3..35be9ba 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "org.literacyapp" minSdkVersion 21 targetSdkVersion 23 - versionCode 1006003 - versionName "1.6.3" + versionCode 1006004 + versionName "1.6.4" // jackOptions { // enabled true diff --git a/app/src/main/java/org/literacyapp/service/synchronization/DownloadContentAsyncTask.java b/app/src/main/java/org/literacyapp/service/synchronization/DownloadContentAsyncTask.java index f65cb36..6ffc850 100644 --- a/app/src/main/java/org/literacyapp/service/synchronization/DownloadContentAsyncTask.java +++ b/app/src/main/java/org/literacyapp/service/synchronization/DownloadContentAsyncTask.java @@ -51,6 +51,7 @@ import org.literacyapp.model.gson.content.LetterGson; import org.literacyapp.model.gson.content.NumberGson; import org.literacyapp.model.gson.content.StoryBookGson; +import org.literacyapp.model.gson.content.SyllableGson; import org.literacyapp.model.gson.content.WordGson; import org.literacyapp.model.gson.content.multimedia.AudioGson; import org.literacyapp.model.gson.content.multimedia.ImageGson; @@ -228,6 +229,41 @@ protected String doInBackground(Void... voids) { } + publishProgress("Downloading Syllables"); + url = EnvironmentSettings.getRestUrl() + "/content/syllable/list" + + "?deviceId=" + DeviceInfoHelper.getDeviceId(context) + + "&locale=" + DeviceInfoHelper.getLocale(context); + jsonResponse = JsonLoader.loadJson(url); + Log.i(getClass().getName(), "jsonResponse: " + jsonResponse); + try { + JSONObject jsonObject = new JSONObject(jsonResponse); + if (!"success".equals(jsonObject.getString("result"))) { + Log.w(getClass().getName(), "Download failed"); + } else { + JSONArray jsonArray = jsonObject.getJSONArray("syllables"); + for (int i = 0; i < jsonArray.length(); i++) { + Type type = new TypeToken(){}.getType(); + SyllableGson syllableGson = new Gson().fromJson(jsonArray.getString(i), type); +// Syllable syllable = GsonToGreenDaoConverter.getSyllable(syllableGson); +// Syllable existingSyllable = syllableDao.queryBuilder() +// .where(SyllableDao.Properties.Id.eq(syllable.getId())) +// .unique(); +// if (existingSyllable == null) { +// Log.i(getClass().getName(), "Storing Syllable, id: " + syllable.getId() + ", text: \"" + syllable.getText() + "\", revisionNumber: " + syllable.getRevisionNumber()); +// syllableDao.insert(syllable); +// } else if (existingSyllable.getRevisionNumber() < syllable.getRevisionNumber()) { +// Log.i(getClass().getName(), "Updating Syllable with id " + existingSyllable.getId() + " from revisionNumber " + existingSyllable.getRevisionNumber() + " to revisionNumber " + syllable.getRevisionNumber()); +// syllableDao.update(syllable); +// } else { +// Log.i(getClass().getName(), "Syllable \"" + syllable.getText() + "\" already exists in database with id " + syllable.getId() + " (revision " + syllable.getRevisionNumber() + ")"); +// } + } + } + } catch (JSONException e) { + Log.e(getClass().getName(), null, e); + } + + publishProgress("Downloading Words"); url = EnvironmentSettings.getRestUrl() + "/content/word/list" + "?deviceId=" + DeviceInfoHelper.getDeviceId(context) + diff --git a/contentprovider/build.gradle b/contentprovider/build.gradle index ad51c24..ece50ed 100644 --- a/contentprovider/build.gradle +++ b/contentprovider/build.gradle @@ -8,8 +8,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 23 - versionCode 1000007 - versionName "1.0.7" + versionCode 1000008 + versionName "1.0.8" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } diff --git a/contentprovider/src/main/java/org/literacyapp/contentprovider/ContentProvider.java b/contentprovider/src/main/java/org/literacyapp/contentprovider/ContentProvider.java index 48faf65..7c88cb2 100644 --- a/contentprovider/src/main/java/org/literacyapp/contentprovider/ContentProvider.java +++ b/contentprovider/src/main/java/org/literacyapp/contentprovider/ContentProvider.java @@ -88,7 +88,7 @@ public static List getUnlockedLetters() { LetterDao letterDao = daoSession.getLetterDao(); - // Copied from CurriculumHelper.java: + // Copied from app/CurriculumHelper.java: List letters = new ArrayList<>(); @@ -144,7 +144,7 @@ public static List getUnlockedNumbers() { NumberDao numberDao = daoSession.getNumberDao(); - // Copied from CurriculumHelper.java: + // Copied from app/CurriculumHelper.java: List numbers = new ArrayList<>(); diff --git a/contentprovider/src/main/java/org/literacyapp/contentprovider/dao/DaoMaster.java b/contentprovider/src/main/java/org/literacyapp/contentprovider/dao/DaoMaster.java index ef509f4..a891acc 100644 --- a/contentprovider/src/main/java/org/literacyapp/contentprovider/dao/DaoMaster.java +++ b/contentprovider/src/main/java/org/literacyapp/contentprovider/dao/DaoMaster.java @@ -39,6 +39,7 @@ public static void createAllTables(Database db, boolean ifNotExists) { VideoDao.createTable(db, ifNotExists); NumberDao.createTable(db, ifNotExists); StoryBookDao.createTable(db, ifNotExists); + SyllableDao.createTable(db, ifNotExists); WordDao.createTable(db, ifNotExists); DeviceDao.createTable(db, ifNotExists); JoinNumbersWithWordsDao.createTable(db, ifNotExists); @@ -68,6 +69,7 @@ public static void dropAllTables(Database db, boolean ifExists) { VideoDao.dropTable(db, ifExists); NumberDao.dropTable(db, ifExists); StoryBookDao.dropTable(db, ifExists); + SyllableDao.dropTable(db, ifExists); WordDao.dropTable(db, ifExists); DeviceDao.dropTable(db, ifExists); JoinNumbersWithWordsDao.dropTable(db, ifExists); @@ -111,6 +113,7 @@ public DaoMaster(Database db) { registerDaoClass(VideoDao.class); registerDaoClass(NumberDao.class); registerDaoClass(StoryBookDao.class); + registerDaoClass(SyllableDao.class); registerDaoClass(WordDao.class); registerDaoClass(DeviceDao.class); registerDaoClass(JoinNumbersWithWordsDao.class); diff --git a/contentprovider/src/main/java/org/literacyapp/contentprovider/dao/DaoSession.java b/contentprovider/src/main/java/org/literacyapp/contentprovider/dao/DaoSession.java index 23210a4..e53eb81 100644 --- a/contentprovider/src/main/java/org/literacyapp/contentprovider/dao/DaoSession.java +++ b/contentprovider/src/main/java/org/literacyapp/contentprovider/dao/DaoSession.java @@ -26,6 +26,7 @@ import org.literacyapp.contentprovider.model.content.multimedia.Video; import org.literacyapp.contentprovider.model.content.Number; import org.literacyapp.contentprovider.model.content.StoryBook; +import org.literacyapp.contentprovider.model.content.Syllable; import org.literacyapp.contentprovider.model.content.Word; import org.literacyapp.contentprovider.model.Device; import org.literacyapp.contentprovider.model.JoinNumbersWithWords; @@ -52,6 +53,7 @@ import org.literacyapp.contentprovider.dao.VideoDao; import org.literacyapp.contentprovider.dao.NumberDao; import org.literacyapp.contentprovider.dao.StoryBookDao; +import org.literacyapp.contentprovider.dao.SyllableDao; import org.literacyapp.contentprovider.dao.WordDao; import org.literacyapp.contentprovider.dao.DeviceDao; import org.literacyapp.contentprovider.dao.JoinNumbersWithWordsDao; @@ -87,6 +89,7 @@ public class DaoSession extends AbstractDaoSession { private final DaoConfig videoDaoConfig; private final DaoConfig numberDaoConfig; private final DaoConfig storyBookDaoConfig; + private final DaoConfig syllableDaoConfig; private final DaoConfig wordDaoConfig; private final DaoConfig deviceDaoConfig; private final DaoConfig joinNumbersWithWordsDaoConfig; @@ -113,6 +116,7 @@ public class DaoSession extends AbstractDaoSession { private final VideoDao videoDao; private final NumberDao numberDao; private final StoryBookDao storyBookDao; + private final SyllableDao syllableDao; private final WordDao wordDao; private final DeviceDao deviceDao; private final JoinNumbersWithWordsDao joinNumbersWithWordsDao; @@ -179,6 +183,9 @@ public DaoSession(Database db, IdentityScopeType type, Map { + + public static final String TABLENAME = "SYLLABLE"; + + /** + * Properties of entity Syllable.
+ * Can be used for QueryBuilder and for referencing column names. + */ + public static class Properties { + public final static Property Id = new Property(0, Long.class, "id", true, "_id"); + public final static Property Locale = new Property(1, String.class, "locale", false, "LOCALE"); + public final static Property TimeLastUpdate = new Property(2, Long.class, "timeLastUpdate", false, "TIME_LAST_UPDATE"); + public final static Property RevisionNumber = new Property(3, Integer.class, "revisionNumber", false, "REVISION_NUMBER"); + public final static Property ContentStatus = new Property(4, String.class, "contentStatus", false, "CONTENT_STATUS"); + public final static Property Text = new Property(5, String.class, "text", false, "TEXT"); + public final static Property UsageCount = new Property(6, int.class, "usageCount", false, "USAGE_COUNT"); + } + + private final LocaleConverter localeConverter = new LocaleConverter(); + private final CalendarConverter timeLastUpdateConverter = new CalendarConverter(); + private final ContentStatusConverter contentStatusConverter = new ContentStatusConverter(); + + public SyllableDao(DaoConfig config) { + super(config); + } + + public SyllableDao(DaoConfig config, DaoSession daoSession) { + super(config, daoSession); + } + + /** Creates the underlying database table. */ + public static void createTable(Database db, boolean ifNotExists) { + String constraint = ifNotExists? "IF NOT EXISTS ": ""; + db.execSQL("CREATE TABLE " + constraint + "\"SYLLABLE\" (" + // + "\"_id\" INTEGER PRIMARY KEY ," + // 0: id + "\"LOCALE\" TEXT NOT NULL ," + // 1: locale + "\"TIME_LAST_UPDATE\" INTEGER," + // 2: timeLastUpdate + "\"REVISION_NUMBER\" INTEGER NOT NULL ," + // 3: revisionNumber + "\"CONTENT_STATUS\" TEXT NOT NULL ," + // 4: contentStatus + "\"TEXT\" TEXT NOT NULL ," + // 5: text + "\"USAGE_COUNT\" INTEGER NOT NULL );"); // 6: usageCount + } + + /** Drops the underlying database table. */ + public static void dropTable(Database db, boolean ifExists) { + String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"SYLLABLE\""; + db.execSQL(sql); + } + + @Override + protected final void bindValues(DatabaseStatement stmt, Syllable entity) { + stmt.clearBindings(); + + Long id = entity.getId(); + if (id != null) { + stmt.bindLong(1, id); + } + stmt.bindString(2, localeConverter.convertToDatabaseValue(entity.getLocale())); + + Calendar timeLastUpdate = entity.getTimeLastUpdate(); + if (timeLastUpdate != null) { + stmt.bindLong(3, timeLastUpdateConverter.convertToDatabaseValue(timeLastUpdate)); + } + stmt.bindLong(4, entity.getRevisionNumber()); + stmt.bindString(5, contentStatusConverter.convertToDatabaseValue(entity.getContentStatus())); + stmt.bindString(6, entity.getText()); + stmt.bindLong(7, entity.getUsageCount()); + } + + @Override + protected final void bindValues(SQLiteStatement stmt, Syllable entity) { + stmt.clearBindings(); + + Long id = entity.getId(); + if (id != null) { + stmt.bindLong(1, id); + } + stmt.bindString(2, localeConverter.convertToDatabaseValue(entity.getLocale())); + + Calendar timeLastUpdate = entity.getTimeLastUpdate(); + if (timeLastUpdate != null) { + stmt.bindLong(3, timeLastUpdateConverter.convertToDatabaseValue(timeLastUpdate)); + } + stmt.bindLong(4, entity.getRevisionNumber()); + stmt.bindString(5, contentStatusConverter.convertToDatabaseValue(entity.getContentStatus())); + stmt.bindString(6, entity.getText()); + stmt.bindLong(7, entity.getUsageCount()); + } + + @Override + public Long readKey(Cursor cursor, int offset) { + return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0); + } + + @Override + public Syllable readEntity(Cursor cursor, int offset) { + Syllable entity = new Syllable( // + cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id + localeConverter.convertToEntityProperty(cursor.getString(offset + 1)), // locale + cursor.isNull(offset + 2) ? null : timeLastUpdateConverter.convertToEntityProperty(cursor.getLong(offset + 2)), // timeLastUpdate + cursor.getInt(offset + 3), // revisionNumber + contentStatusConverter.convertToEntityProperty(cursor.getString(offset + 4)), // contentStatus + cursor.getString(offset + 5), // text + cursor.getInt(offset + 6) // usageCount + ); + return entity; + } + + @Override + public void readEntity(Cursor cursor, Syllable entity, int offset) { + entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0)); + entity.setLocale(localeConverter.convertToEntityProperty(cursor.getString(offset + 1))); + entity.setTimeLastUpdate(cursor.isNull(offset + 2) ? null : timeLastUpdateConverter.convertToEntityProperty(cursor.getLong(offset + 2))); + entity.setRevisionNumber(cursor.getInt(offset + 3)); + entity.setContentStatus(contentStatusConverter.convertToEntityProperty(cursor.getString(offset + 4))); + entity.setText(cursor.getString(offset + 5)); + entity.setUsageCount(cursor.getInt(offset + 6)); + } + + @Override + protected final Long updateKeyAfterInsert(Syllable entity, long rowId) { + entity.setId(rowId); + return rowId; + } + + @Override + public Long getKey(Syllable entity) { + if(entity != null) { + return entity.getId(); + } else { + return null; + } + } + + @Override + public boolean hasKey(Syllable entity) { + return entity.getId() != null; + } + + @Override + protected final boolean isEntityUpdateable() { + return true; + } + +} diff --git a/contentprovider/src/main/java/org/literacyapp/contentprovider/model/content/Syllable.java b/contentprovider/src/main/java/org/literacyapp/contentprovider/model/content/Syllable.java new file mode 100644 index 0000000..45ce6d7 --- /dev/null +++ b/contentprovider/src/main/java/org/literacyapp/contentprovider/model/content/Syllable.java @@ -0,0 +1,118 @@ +package org.literacyapp.contentprovider.model.content; + +import org.greenrobot.greendao.annotation.Convert; +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Generated; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.NotNull; +import org.literacyapp.contentprovider.dao.converter.CalendarConverter; +import org.literacyapp.contentprovider.dao.converter.ContentStatusConverter; +import org.literacyapp.contentprovider.dao.converter.LocaleConverter; +import org.literacyapp.contentprovider.dao.converter.SpellingConsistencyConverter; +import org.literacyapp.model.enums.Locale; +import org.literacyapp.model.enums.content.ContentStatus; +import org.literacyapp.model.enums.content.SpellingConsistency; + +import java.util.Calendar; + +/** + * Based on {@link org.literacyapp.model.gson.content.SyllableGson} + */ +@Entity +public class Syllable { + + @Id + private Long id; + + @NotNull + @Convert(converter = LocaleConverter.class, columnType = String.class) + private Locale locale; + + @Convert(converter = CalendarConverter.class, columnType = Long.class) + private Calendar timeLastUpdate; + + @NotNull + private Integer revisionNumber; // [1, 2, 3, ...] + + @NotNull + @Convert(converter = ContentStatusConverter.class, columnType = String.class) + private ContentStatus contentStatus; + + @NotNull + private String text; + + private int usageCount; + + @Generated(hash = 1434371881) + public Syllable(Long id, @NotNull Locale locale, Calendar timeLastUpdate, + @NotNull Integer revisionNumber, @NotNull ContentStatus contentStatus, + @NotNull String text, int usageCount) { + this.id = id; + this.locale = locale; + this.timeLastUpdate = timeLastUpdate; + this.revisionNumber = revisionNumber; + this.contentStatus = contentStatus; + this.text = text; + this.usageCount = usageCount; + } + + @Generated(hash = 1469233490) + public Syllable() { + } + + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public Locale getLocale() { + return this.locale; + } + + public void setLocale(Locale locale) { + this.locale = locale; + } + + public Calendar getTimeLastUpdate() { + return this.timeLastUpdate; + } + + public void setTimeLastUpdate(Calendar timeLastUpdate) { + this.timeLastUpdate = timeLastUpdate; + } + + public Integer getRevisionNumber() { + return this.revisionNumber; + } + + public void setRevisionNumber(Integer revisionNumber) { + this.revisionNumber = revisionNumber; + } + + public ContentStatus getContentStatus() { + return this.contentStatus; + } + + public void setContentStatus(ContentStatus contentStatus) { + this.contentStatus = contentStatus; + } + + public String getText() { + return this.text; + } + + public void setText(String text) { + this.text = text; + } + + public int getUsageCount() { + return this.usageCount; + } + + public void setUsageCount(int usageCount) { + this.usageCount = usageCount; + } +}