package net.sabi.pester; import java.util.Comparator; import danger.app.Application; import danger.app.DataStore; import danger.app.Event; import danger.app.SettingsDB; import danger.app.SettingsDBException; import danger.internal.Date; import danger.util.StdActiveList; import danger.util.DEBUG; public class Alarms extends StdActiveList { // max # records in a datastore public static final int MAX_ALARM_COUNT = 50; private static Alarms sAlarmList = null; private static Listener sListener; private static SettingsDB sSettingsDB; private DataStore mDataStore; private Alarms() { mDataStore = DataStore.createDataStore("alarms", true /* auto sync */); // register us for Event.EVENT_DATASTORE_RESTORED, which only // seems to be documented at: // mDataStore.setAutoSyncNotifyee(sListener); refreshFromDataStore(false); } void refreshFromDataStore(boolean datastoreRestored) { sAlarmList = null; removeAllItems(); if (datastoreRestored) mDataStore.doneResolvingConflict(); // resolves UID conflicts byte[][] alarmsData = mDataStore.getRecords(); int i; for (i = 0 ; i < alarmsData.length ; ++i) { Alarm alarm = new Alarm(); alarm.fromByteArray(alarmsData[i]); alarm.setUID(mDataStore.getRecordUID(i)); insertItemSorted(alarm, alarm); alarm.resume(); } try { MessageFinder.setMessageListFromByteArray(sSettingsDB.getBytes(KEY_RECENT_MESSAGES)); } catch (SettingsDBException e) { MessageFinder.setDefaultMessageList(); } sAlarmList = this; } public static Alarms getList() { if (sAlarmList == null) { sSettingsDB = new SettingsDB("settings", true /* auto sync */); sListener = new Listener(); new Alarms(); Application.registerForEvent(sListener, Event.EVENT_TIME_CHANGED); } return sAlarmList; } public static boolean canCreateAlarm() { return (sAlarmList.size() < MAX_ALARM_COUNT); } public static void addAlarm(Alarm alarm) { sAlarmList.insertItemSorted(alarm, alarm); } public static void removeAlarm(Alarm alarm) { sAlarmList.removeItem(alarm); } public static void recentMessagesChanged() { sSettingsDB.setBytes(KEY_RECENT_MESSAGES, MessageFinder.messageListAsByteArray()); } protected void onItemAdded(Object item, int index) { if (sAlarmList == null) // restoring from service return; Alarm alarm = (Alarm)item; DEBUG.p("adding: " + alarm + " next UID: " + mDataStore.getAutoSyncNextUID()); index = mDataStore.addRecord(alarm.toByteArray()); alarm.setUID(mDataStore.getRecordUID(index)); DEBUG.p("added UID " + alarm.getUID() + " @ " + index); } protected void onItemRemoved(Object item, int index) { if (sAlarmList == null) // restoring from service (after hard reset) return; Alarm alarm = (Alarm)item; int uid = alarm.getUID(); if (uid == 0) return; mDataStore.removeRecordByUID(uid); DEBUG.p("removed UID " + alarm.getUID()); } public void onItemUpdated(Object item, int index) { if (sAlarmList == null) // restoring from service return; Alarm alarm = (Alarm)item; mDataStore.setRecordDataByUID(alarm.getUID(), alarm.toByteArray(), true); DEBUG.p("updated: " + alarm + " UID " + alarm.getUID()); } private static String KEY_DEFAULT_ALARM = "default alarm"; private static String KEY_RECENT_MESSAGES = "recent messages"; public static Alarm getDefaultAlarm() { Alarm defaultAlarm = new Alarm(); try { defaultAlarm.fromByteArray(sSettingsDB.getBytes(KEY_DEFAULT_ALARM)); } catch (SettingsDBException e) { defaultAlarm = new Alarm(); defaultAlarm.setDate(new Date()); defaultAlarm.setPeriod(600, false); } return defaultAlarm; } public static void setDefaultAlarm(Alarm alarm) { sSettingsDB.setBytes(KEY_DEFAULT_ALARM, alarm.toByteArray()); } static class Listener extends danger.app.Listener implements danger.util.ActiveList.ForEach { public void receive(Object item) { ((Alarm)item).timeChanged(); } public boolean receiveEvent(Event e) { if (e.type == Event.EVENT_TIME_CHANGED) { Alarms.getList().forEach(this); return true; } else if (e.type == Event.EVENT_DATASTORE_RESTORED) { String dbName = (String)e.argument; DEBUG.p("DATASTORE_RESTORED: " + dbName); if (!dbName.endsWith("alarms")) { // because we only get/set the default alarm on demand // there's no need to handle conflicts with the settings... // XXX but what happens if we set a (default) alarm, then // the SettingsDB restores? Alarms.getList().refreshFromDataStore(true); } } return super.receiveEvent(e); } } }