It's imposible that everything works completely, but at least it compiles...

pull/14/head
Tim Su 14 years ago
parent c38890a885
commit b66e28dfb8

@ -4,7 +4,7 @@
<classpathentry kind="src" path="src-legacy"/> <classpathentry kind="src" path="src-legacy"/>
<classpathentry kind="src" path="api-src"/> <classpathentry kind="src" path="api-src"/>
<classpathentry kind="src" path="common-src"/> <classpathentry kind="src" path="common-src"/>
<classpathentry excluding="com/todoroo/astrid/rmilk/DetailExposer.java|com/todoroo/astrid/rmilk/EditOperationExposer.java|com/todoroo/astrid/rmilk/FilterExposer.java|com/todoroo/astrid/rmilk/MilkEditActivity.java|com/todoroo/astrid/rmilk/StartupReceiver.java" kind="src" path="plugin-src"/> <classpathentry excluding="com/todoroo/astrid/rmilk/DetailExposer.java|com/todoroo/astrid/rmilk/EditOperationExposer.java|com/todoroo/astrid/rmilk/MilkEditActivity.java|com/todoroo/astrid/rmilk/StartupReceiver.java" kind="src" path="plugin-src"/>
<classpathentry kind="src" path="gen"/> <classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="lib" path="lib/commons-codec-1.3.jar"/> <classpathentry exported="true" kind="lib" path="lib/commons-codec-1.3.jar"/>

@ -173,4 +173,18 @@ public class AndroidUtilities {
return result; return result;
} }
/**
* Returns true if a and b or null or a.equals(b)
* @param a
* @param b
* @return
*/
public static boolean equals(Object a, Object b) {
if(a == null && b == null)
return true;
if(a == null)
return false;
return a.equals(b);
}
} }

@ -4,10 +4,12 @@
package com.todoroo.astrid.rmilk; package com.todoroo.astrid.rmilk;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import com.todoroo.astrid.R; import com.timsu.astrid.R;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterCategory; import com.todoroo.astrid.api.FilterCategory;
@ -15,6 +17,7 @@ import com.todoroo.astrid.api.FilterListHeader;
import com.todoroo.astrid.api.FilterListItem; import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.rmilk.Utilities.ListContainer; import com.todoroo.astrid.rmilk.Utilities.ListContainer;
import com.todoroo.astrid.rmilk.data.MilkDataService; import com.todoroo.astrid.rmilk.data.MilkDataService;
import com.todoroo.astrid.rmilk.data.MilkTask;
/** /**
* Exposes filters based on RTM lists * Exposes filters based on RTM lists
@ -30,9 +33,10 @@ public class FilterExposer extends BroadcastReceiver {
String listTitle = context.getString(R.string.rmilk_FEx_list_item). String listTitle = context.getString(R.string.rmilk_FEx_list_item).
replace("$N", list.name).replace("$C", Integer.toString(list.count)); replace("$N", list.name).replace("$C", Integer.toString(list.count));
String title = context.getString(R.string.rmilk_FEx_list_title, list.name); String title = context.getString(R.string.rmilk_FEx_list_title, list.name);
Filter filter = new Filter(listTitle, title, ContentValues values = new ContentValues(); // TODO
"TODO", Filter filter = new Filter(Utilities.IDENTIFIER, listTitle, title,
"TODO"); new QueryTemplate().join(MilkDataService.MILK_JOIN).where(MilkTask.LIST_ID.eq(list.id)),
values);
return filter; return filter;
} }
@ -54,8 +58,9 @@ public class FilterExposer extends BroadcastReceiver {
for(int i = 0; i < lists.length; i++) for(int i = 0; i < lists.length; i++)
listFilters[i] = filterFromList(context, lists[i]); listFilters[i] = filterFromList(context, lists[i]);
FilterListHeader rtmHeader = new FilterListHeader(context.getString(R.string.rmilk_FEx_header)); FilterListHeader rtmHeader = new FilterListHeader(Utilities.IDENTIFIER,
FilterCategory rtmLists = new FilterCategory( context.getString(R.string.rmilk_FEx_header));
FilterCategory rtmLists = new FilterCategory(Utilities.IDENTIFIER,
context.getString(R.string.rmilk_FEx_list), listFilters); context.getString(R.string.rmilk_FEx_list), listFilters);
// transmit filter list // transmit filter list
@ -63,7 +68,7 @@ public class FilterExposer extends BroadcastReceiver {
list[0] = rtmHeader; list[0] = rtmHeader;
list[1] = rtmLists; list[1] = rtmLists;
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS); Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_SEND_FILTERS);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_ITEMS, list); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_RESPONSE, list);
context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); context.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
} }

@ -61,7 +61,7 @@ public class MilkPreferences extends PreferenceActivity {
getString(R.string.rmilk_MPr_sync_key)); getString(R.string.rmilk_MPr_sync_key));
syncAction.setOnPreferenceClickListener(new OnPreferenceClickListener() { syncAction.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference p) { public boolean onPreferenceClick(Preference p) {
new RTMSyncProvider().synchronize(MilkPreferences.this); new RTMSyncProvider().synchronize();
return true; return true;
} }
}); });

@ -22,6 +22,11 @@ import com.todoroo.astrid.rmilk.data.MilkList;
@SuppressWarnings("nls") @SuppressWarnings("nls")
public class Utilities { public class Utilities {
// --- constants
/** add-on identifier */
public static final String IDENTIFIER = "rmilk";
// --- helper classes // --- helper classes
/** /**
@ -50,19 +55,6 @@ public class Utilities {
public int count; public int count;
} }
// --- Metadata keys
// NOTE: no sql escaping is provided for keys
public static final String KEY_LIST_ID = "rmilk_listId";
public static final String KEY_TASK_SERIES_ID = "rmilk_taskSeriesId";
public static final String KEY_TASK_ID = "rmilk_taskId";
public static final String KEY_REPEAT = "rmilk_repeat";
public static final String KEY_UPDATED = "rmilk_updated";
// --- Preference Keys // --- Preference Keys
private static final String PREF_TOKEN = "rmilk_token"; private static final String PREF_TOKEN = "rmilk_token";

@ -26,18 +26,21 @@ public class RtmList extends RtmData {
private final String id; private final String id;
private final boolean smart; private final boolean smart;
private final boolean archived;
private final String name; private final String name;
public RtmList(String id, String name, boolean smart) { public RtmList(String id, String name, boolean smart) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.smart = smart; this.smart = smart;
this.archived = false;
} }
public RtmList(Element elt) { public RtmList(Element elt) {
id = elt.getAttribute("id"); id = elt.getAttribute("id");
name = elt.getAttribute("name"); name = elt.getAttribute("name");
smart = elt.getAttribute("smart") == "1"; smart = elt.getAttribute("smart") == "1";
archived = elt.getAttribute("archived") == "1";
} }
public String getId() { public String getId() {
@ -51,4 +54,8 @@ public class RtmList extends RtmData {
public boolean isSmart() { public boolean isSmart() {
return smart; return smart;
} }
public boolean isArchived() {
return archived;
}
} }

@ -3,164 +3,87 @@
*/ */
package com.todoroo.astrid.rmilk.data; package com.todoroo.astrid.rmilk.data;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import android.content.Context; import android.content.Context;
import android.database.sqlite.SQLiteQueryBuilder;
import com.todoroo.andlib.data.GenericDao; import com.todoroo.andlib.data.GenericDao;
import com.todoroo.andlib.data.Property; import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.data.Property.IntegerProperty; import com.todoroo.andlib.data.Property.CountProperty;
import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.astrid.dao.Database; import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.Order;
import com.todoroo.andlib.sql.Query;
import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.model.Metadata;
import com.todoroo.astrid.model.Task; import com.todoroo.astrid.model.Task;
import com.todoroo.astrid.rmilk.Utilities;
import com.todoroo.astrid.rmilk.Utilities.ListContainer; import com.todoroo.astrid.rmilk.Utilities.ListContainer;
import com.todoroo.astrid.rmilk.api.data.RtmList; import com.todoroo.astrid.rmilk.api.data.RtmList;
import com.todoroo.astrid.rmilk.api.data.RtmLists; import com.todoroo.astrid.rmilk.api.data.RtmLists;
import com.todoroo.astrid.service.MetadataService;
@SuppressWarnings("nls")
public class MilkDataService { public class MilkDataService {
// --- constants
/** for joining milk task table with task table */
public static final Join MILK_JOIN = Join.left(MilkTask.TABLE,
Task.ID.eq(MilkTask.TASK));
// --- instance variables
protected final Context context; protected final Context context;
private final MilkDatabase milkDatabase = new MilkDatabase(); private final MilkDatabase milkDatabase = new MilkDatabase();
@Autowired private final GenericDao<MilkList> milkListDao;
private MetadataService metadataService; private final GenericDao<MilkTask> milkTaskDao;
private final GenericDao<MilkList> listDao;
@Autowired @Autowired
private TaskDao taskDao; private TaskDao taskDao;
@Autowired
private Database database;
static final Random random = new Random(); static final Random random = new Random();
public MilkDataService(Context context) { public MilkDataService(Context context) {
this.context = context; this.context = context;
DependencyInjectionService.getInstance().inject(this); DependencyInjectionService.getInstance().inject(this);
listDao = new GenericDao<MilkList>(MilkList.class, milkDatabase); milkListDao = new GenericDao<MilkList>(MilkList.class, milkDatabase);
milkTaskDao = new GenericDao<MilkTask>(MilkTask.class, milkDatabase);
milkDatabase.openForReading();
} }
// --- RTM properties
/** RTM List id */
public static final StringJoinProperty LIST_ID =
new StringJoinProperty(Utilities.KEY_LIST_ID);
/** RTM Task Series id */
public static final StringJoinProperty TASK_SERIES_ID =
new StringJoinProperty(Utilities.KEY_TASK_SERIES_ID);
/** RTM Task id */
public static final StringJoinProperty TASK_ID =
new StringJoinProperty(Utilities.KEY_TASK_ID);
/** 1 if task repeats in RTM, 0 otherwise */
public static final IntegerJoinProperty REPEAT =
new IntegerJoinProperty(Utilities.KEY_REPEAT);
/** 1 if task was updated since last sync, 0 otherwise */
public static final IntegerJoinProperty UPDATED =
new IntegerJoinProperty(Utilities.KEY_UPDATED);
// --- non-RTM properties we synchronize
public static final StringJoinProperty TAGS =
new StringJoinProperty(com.todoroo.astrid.tags.TagService.KEY);
// --- task and metadata methods // --- task and metadata methods
/** Properties to fetch when user wants to view / edit tasks */
public static final Property<?>[] RTM_PROPERTIES = new Property<?>[] {
Task.ID,
LIST_ID,
TASK_SERIES_ID,
TASK_ID,
REPEAT
};
/**
* Read a single task by task id
* @param taskId
* @return item, or null if it doesn't exist
*/
public Task readTask(long taskId) {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(createJoinClause(RTM_PROPERTIES));
TodorooCursor<Task> cursor =
taskDao.query(database, RTM_PROPERTIES, builder,
Task.ID.qualifiedName()+ " = " + taskId,
null, null);
try {
if (cursor.getCount() == 0)
return null;
cursor.moveToFirst();
Task task = new Task(cursor, RTM_PROPERTIES);
return task;
} finally {
cursor.close();
}
}
/** Helper method for building a join clause for task/metadata joins */
public static String createJoinClause(Property<?>[] properties) {
StringBuilder stringBuilder = new StringBuilder(Database.TASK_TABLE);
int joinTableCount = 0;
for(Property<?> property : properties) {
if(property instanceof JoinProperty) {
JoinProperty jp = (JoinProperty)property;
stringBuilder.append(" LEFT JOIN (").append(jp.joinTable()).
append(") m").append(++joinTableCount).
append(" ON ").append(Task.ID_PROPERTY).append(" = m").
append(joinTableCount).append('.').append(Metadata.TASK.name).
append(' ');
}
}
return stringBuilder.toString();
}
/** /**
* Clears RTM metadata information. Used when user logs out of RTM * Clears RTM metadata information. Used when user logs out of RTM
*/ */
public void clearMetadata() { public void clearMetadata() {
metadataService.deleteWhere(String.format("%s = '%s' OR %s = '%s' " + milkTaskDao.deleteWhere(Criterion.all);
"OR %s = '%s OR %s = '%s'",
Metadata.KEY, LIST_ID,
Metadata.KEY, TASK_SERIES_ID,
Metadata.KEY, TASK_ID,
Metadata.KEY, REPEAT));
} }
/**
* Gets tasks that were created since last sync
* @param properties
* @return
*/
public TodorooCursor<Task> getLocallyCreated(Property<?>[] properties) { public TodorooCursor<Task> getLocallyCreated(Property<?>[] properties) {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); return
builder.setTables(createJoinClause(properties)); taskDao.query(Query.select(properties).join(MILK_JOIN).where(
TodorooCursor<Task> cursor = Criterion.or(MilkTask.UPDATED.eq(0), MilkTask.TASK.isNull())));
taskDao.query(database, properties, builder,
TASK_ID + " ISNULL",
null, null);
return cursor;
} }
/**
* Gets tasks that were modified since last sync
* @param properties
* @return
*/
public TodorooCursor<Task> getLocallyUpdated(Property<?>[] properties) { public TodorooCursor<Task> getLocallyUpdated(Property<?>[] properties) {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); return
builder.setTables(createJoinClause(properties)); taskDao.query(Query.select(properties).join(MILK_JOIN).
TodorooCursor<Task> cursor = where(Criterion.and(MilkTask.UPDATED.neq(0),
taskDao.query(database, properties, builder, MilkTask.UPDATED.lt(Task.MODIFICATION_DATE))));
"NOT " + TASK_ID + " ISNULL", // TODO wrong!
null, null);
return cursor;
} }
// --- list methods // --- list methods
@ -171,17 +94,15 @@ public class MilkDataService {
* @return null if no list by this id exists, otherwise list name * @return null if no list by this id exists, otherwise list name
*/ */
public String getList(String listId) { public String getList(String listId) {
pluginDatabase.open(context); TodorooCursor<MilkList> cursor = milkListDao.query(Query.select(
TodorooCursor<List> cursor = listDao.fetch(pluginDatabase, MilkList.NAME).where(MilkList.ID.eq(listId)));
List.PROPERTIES, ListSql.withId(listId), null, "1"); //$NON-NLS-1$
try { try {
if(cursor.getCount() == 0) if(cursor.getCount() == 0)
return null; return null;
cursor.moveToFirst(); cursor.moveToFirst();
return cursor.get(List.NAME); return cursor.get(MilkList.NAME);
} finally { } finally {
cursor.close(); cursor.close();
pluginDatabase.close();
} }
} }
@ -190,49 +111,26 @@ public class MilkDataService {
* @return * @return
*/ */
public ListContainer[] getListsWithCounts() { public ListContainer[] getListsWithCounts() {
// read all list titles CountProperty COUNT = new CountProperty();
pluginDatabase.open(context);
TodorooCursor<List> listCursor = listDao.fetch(pluginDatabase,
List.PROPERTIES, null);
HashMap<String, ListContainer> listIdToContainerMap;
try {
int count = listCursor.getCount();
if(count == 0)
return new ListContainer[0];
listIdToContainerMap =
new HashMap<String, ListContainer>(count);
List list = new List();
for(int i = 0; i < count; i++) {
listCursor.moveToNext();
list.readFromCursor(listCursor, List.PROPERTIES);
ListContainer container = new ListContainer(list);
listIdToContainerMap.put(container.id, container);
}
} finally {
listCursor.close();
}
// read all list counts // read all list counts
IntegerProperty countProperty = Property.countProperty(); TodorooCursor<MilkTask> cursor = milkTaskDao.query(Query.select(MilkList.ID, MilkList.NAME, COUNT).
TodorooCursor<Metadata> metadataCursor = metadataService.fetchWithCount( join(Join.inner(MilkList.TABLE, MilkTask.LIST_ID.eq(MilkList.ID))).
MetadataSql.withKey(Utilities.KEY_LIST_ID), Metadata.VALUE + " ASC", false); //$NON-NLS-1$ orderBy(Order.asc(MilkList.POSITION), Order.asc(MilkList.ID)).
ListContainer[] containers = new ListContainer[metadataCursor.getCount()]; groupBy(MilkTask.LIST_ID));
ListContainer[] containers = new ListContainer[cursor.getCount()];
try { try {
for(int i = 0; i < containers.length; i++) { for(int i = 0; i < containers.length; i++) {
metadataCursor.moveToNext(); cursor.moveToNext();
String id = metadataCursor.get(Metadata.VALUE); long id = cursor.get(MilkList.ID);
ListContainer container = listIdToContainerMap.get(id); String name = cursor.get(MilkList.NAME);
if(container == null) { int count = cursor.get(COUNT);
container = new ListContainer(id, "[unknown]"); //$NON-NLS-1$ containers[i] = new ListContainer(id, name);
} containers[i].count = count;
container.count = metadataCursor.get(countProperty);
containers[i] = container;
} }
return containers; return containers;
} finally { } finally {
metadataCursor.close(); cursor.close();
pluginDatabase.close();
} }
} }
@ -240,10 +138,10 @@ public class MilkDataService {
* Get RTM lists as strings * Get RTM lists as strings
* @return * @return
*/ */
public ListContainer[] getLists() { /*public ListContainer[] getLists() {
// read all list titles // read all list titles
pluginDatabase.open(context); milkDatabase.open(context);
TodorooCursor<List> cursor = listDao.fetch(pluginDatabase, TodorooCursor<MilkList> cursor = milkListDao.fetch(milkDatabase,
List.PROPERTIES, null, List.ID + " ASC"); //$NON-NLS-1$ List.PROPERTIES, null, List.ID + " ASC"); //$NON-NLS-1$
ListContainer[] containers = new ListContainer[cursor.getCount()]; ListContainer[] containers = new ListContainer[cursor.getCount()];
try { try {
@ -257,25 +155,22 @@ public class MilkDataService {
return containers; return containers;
} finally { } finally {
cursor.close(); cursor.close();
pluginDatabase.close(); milkDatabase.close();
} }
} }*/
/** /**
* Clears current cache of RTM lists and re-populates * Clears current cache of RTM lists and re-populates
* @param lists * @param lists
*/ */
public void setLists(RtmLists lists) { public void setLists(RtmLists lists) {
pluginDatabase.open(context); milkListDao.deleteWhere(Criterion.all);
try { MilkList model = new MilkList();
List model = new List(); for(Map.Entry<String, RtmList> list : lists.getLists().entrySet()) {
for(Map.Entry<String, RtmList> list : lists.getLists().entrySet()) { model.setValue(MilkList.ID, Long.parseLong(list.getValue().getId()));
model.setValue(List.ID, list.getValue().getId()); model.setValue(MilkList.NAME, list.getValue().getName());
model.setValue(List.NAME, list.getValue().getName()); model.setValue(MilkList.ARCHIVED, list.getValue().isArchived()? 1 : 0);
listDao.save(pluginDatabase, model); milkListDao.createNew(model);
}
} finally {
pluginDatabase.close();
} }
} }

@ -0,0 +1,104 @@
/**
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.rmilk.data;
import android.content.ContentValues;
import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.Table;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.data.Property.IntegerProperty;
import com.todoroo.andlib.data.Property.LongProperty;
import com.todoroo.astrid.model.Task;
/**
* Data Model which represents a list in RTM
*
* @author Tim Su <tim@todoroo.com>
*
*/
@SuppressWarnings("nls")
public class MilkTask extends AbstractModel {
// --- table
public static final Table TABLE = new Table("tasks", MilkTask.class);
// --- properties
/** Task Id */
public static final LongProperty TASK = new LongProperty(
TABLE, "task");
/** {@link MilkList} id */
public static final LongProperty LIST_ID = new LongProperty(
TABLE, "listId");
/** RTM Task Id */
public static final LongProperty TASK_SERIES_ID = new LongProperty(
TABLE, "taskSeriesId");
/** RTM Task Series Id */
public static final LongProperty TASK_ID = new LongProperty(
TABLE, "taskId");
/** Whether task repeats in RTM (1 or 0) */
public static final IntegerProperty REPEATING = new IntegerProperty(
TABLE, "repeating");
/** Unixtime task was last updated in RTM */
public static final LongProperty UPDATED = new LongProperty(
TABLE, "updated");
/** List of all properties for this model */
public static final Property<?>[] PROPERTIES = generateProperties(MilkTask.class);
// --- defaults
/** Default values container */
private static final ContentValues defaultValues = new ContentValues();
static {
defaultValues.put(REPEATING.name, 0);
defaultValues.put(UPDATED.name, 0);
}
@Override
public ContentValues getDefaultValues() {
return defaultValues;
}
// --- data access boilerplate
public MilkTask() {
super();
}
public MilkTask(TodorooCursor<MilkTask> cursor) {
this();
readPropertiesFromCursor(cursor);
}
public void readFromCursor(TodorooCursor<MilkTask> cursor) {
super.readPropertiesFromCursor(cursor);
}
@Override
public long getId() {
return getIdHelper(TASK);
};
// --- parcelable helpers
private static final Creator<Task> CREATOR = new ModelCreator<Task>(Task.class);
@Override
protected Creator<? extends AbstractModel> getCreator() {
return CREATOR;
}
}

@ -41,6 +41,7 @@ import com.todoroo.astrid.rmilk.api.data.RtmTasks;
import com.todoroo.astrid.rmilk.api.data.RtmAuth.Perms; import com.todoroo.astrid.rmilk.api.data.RtmAuth.Perms;
import com.todoroo.astrid.rmilk.api.data.RtmTask.Priority; import com.todoroo.astrid.rmilk.api.data.RtmTask.Priority;
import com.todoroo.astrid.rmilk.data.MilkDataService; import com.todoroo.astrid.rmilk.data.MilkDataService;
import com.todoroo.astrid.rmilk.data.MilkTask;
import com.todoroo.astrid.service.AstridDependencyInjector; import com.todoroo.astrid.service.AstridDependencyInjector;
public class RTMSyncProvider extends SynchronizationProvider { public class RTMSyncProvider extends SynchronizationProvider {
@ -284,11 +285,11 @@ public class RTMSyncProvider extends SynchronizationProvider {
Task.CREATION_DATE, Task.CREATION_DATE,
Task.COMPLETION_DATE, Task.COMPLETION_DATE,
Task.DELETION_DATE, Task.DELETION_DATE,
MilkDataService.LIST_ID, MilkTask.LIST_ID,
MilkDataService.TASK_SERIES_ID, MilkTask.TASK_SERIES_ID,
MilkDataService.TASK_ID, MilkTask.TASK_ID,
MilkDataService.REPEAT, MilkTask.REPEATING,
MilkDataService.TAGS, // TODO tags
}; };
// fetch locally created tasks // fetch locally created tasks
@ -320,12 +321,12 @@ public class RTMSyncProvider extends SynchronizationProvider {
* @return * @return
*/ */
private boolean shouldTransmit(Task task, Property<?> property, Task remoteTask) { private boolean shouldTransmit(Task task, Property<?> property, Task remoteTask) {
if(!task.hasValue(property)) if(!task.containsValue(property))
return false; return false;
if(remoteTask == null) if(remoteTask == null)
return true; return true;
if(!remoteTask.hasValue(property)) if(!remoteTask.containsValue(property))
return true; return true;
return !AndroidUtilities.equals(task.getValue(property), remoteTask.getValue(property)); return !AndroidUtilities.equals(task.getValue(property), remoteTask.getValue(property));
} }
@ -333,8 +334,8 @@ public class RTMSyncProvider extends SynchronizationProvider {
@Override @Override
protected void create(Task task) throws IOException { protected void create(Task task) throws IOException {
String listId = null; String listId = null;
if(task.hasValue(MilkDataService.LIST_ID)) if(task.containsValue(MilkTask.LIST_ID))
listId = task.getValue(MilkDataService.LIST_ID); listId = Long.toString(task.getValue(MilkTask.LIST_ID));
RtmTaskSeries rtmTask = rtmService.tasks_add(timeline, listId, RtmTaskSeries rtmTask = rtmService.tasks_add(timeline, listId,
task.getValue(Task.TITLE)); task.getValue(Task.TITLE));
@ -360,7 +361,7 @@ public class RTMSyncProvider extends SynchronizationProvider {
if(shouldTransmit(task, Task.DUE_DATE, remoteTask)) if(shouldTransmit(task, Task.DUE_DATE, remoteTask))
rtmService.tasks_setDueDate(timeline, id.listId, id.taskSeriesId, rtmService.tasks_setDueDate(timeline, id.listId, id.taskSeriesId,
id.taskId, DateUtilities.unixtimeToDate(task.getValue(Task.DUE_DATE)), id.taskId, DateUtilities.unixtimeToDate(task.getValue(Task.DUE_DATE)),
task.getValue(Task.URGENCY) == Task.URGENCY_SPECIFIC_DAY_TIME); task.hasDueTime());
if(shouldTransmit(task, Task.COMPLETION_DATE, remoteTask)) { if(shouldTransmit(task, Task.COMPLETION_DATE, remoteTask)) {
if(task.getValue(Task.COMPLETION_DATE) == 0) if(task.getValue(Task.COMPLETION_DATE) == 0)
rtmService.tasks_uncomplete(timeline, id.listId, id.taskSeriesId, rtmService.tasks_uncomplete(timeline, id.listId, id.taskSeriesId,
@ -373,8 +374,8 @@ public class RTMSyncProvider extends SynchronizationProvider {
rtmService.tasks_delete(timeline, id.listId, id.taskSeriesId, rtmService.tasks_delete(timeline, id.listId, id.taskSeriesId,
id.taskId); id.taskId);
if(shouldTransmit(task, MilkDataService.LIST_ID, remoteTask) && remoteTask != null) if(shouldTransmit(task, MilkTask.LIST_ID, remoteTask) && remoteTask != null)
rtmService.tasks_moveTo(timeline, remoteTask.getValue(MilkDataService.LIST_ID), rtmService.tasks_moveTo(timeline, Long.toString(remoteTask.getValue(MilkTask.LIST_ID)),
id.listId, id.taskSeriesId, id.taskId); id.listId, id.taskSeriesId, id.taskId);
} }
@ -382,10 +383,10 @@ public class RTMSyncProvider extends SynchronizationProvider {
private Task parseRemoteTask(RtmTaskSeries rtmTaskSeries) { private Task parseRemoteTask(RtmTaskSeries rtmTaskSeries) {
Task task = new Task(); Task task = new Task();
task.setValue(MilkDataService.LIST_ID, rtmTaskSeries.getList().getId()); task.setValue(MilkTask.LIST_ID, Long.parseLong(rtmTaskSeries.getList().getId()));
task.setValue(MilkDataService.TASK_SERIES_ID, rtmTaskSeries.getId()); task.setValue(MilkTask.TASK_SERIES_ID, Long.parseLong(rtmTaskSeries.getId()));
task.setValue(Task.TITLE, rtmTaskSeries.getName()); task.setValue(Task.TITLE, rtmTaskSeries.getName());
task.setValue(MilkDataService.REPEAT, rtmTaskSeries.hasRecurrence() ? 1 : 0); task.setValue(MilkTask.REPEATING, rtmTaskSeries.hasRecurrence() ? 1 : 0);
RtmTask rtmTask = rtmTaskSeries.getTask(); RtmTask rtmTask = rtmTaskSeries.getTask();
if(rtmTask != null) { if(rtmTask != null) {
@ -393,18 +394,16 @@ public class RTMSyncProvider extends SynchronizationProvider {
task.setValue(Task.COMPLETION_DATE, DateUtilities.dateToUnixtime(rtmTask.getCompleted())); task.setValue(Task.COMPLETION_DATE, DateUtilities.dateToUnixtime(rtmTask.getCompleted()));
task.setValue(Task.DELETION_DATE, DateUtilities.dateToUnixtime(rtmTask.getDeleted())); task.setValue(Task.DELETION_DATE, DateUtilities.dateToUnixtime(rtmTask.getDeleted()));
if(rtmTask.getDue() != null) { if(rtmTask.getDue() != null) {
task.setValue(Task.DUE_DATE, DateUtilities.dateToUnixtime(rtmTask.getDue())); task.setValue(Task.DUE_DATE,
if(rtmTask.getHasDueTime()) task.createDueDate(rtmTask.getHasDueTime() ? Task.URGENCY_SPECIFIC_DAY_TIME :
task.setValue(Task.URGENCY, Task.URGENCY_SPECIFIC_DAY_TIME); Task.URGENCY_SPECIFIC_DAY, DateUtilities.dateToUnixtime(rtmTask.getDue())));
else
task.setValue(Task.URGENCY, Task.URGENCY_SPECIFIC_DAY);
} else { } else {
task.setValue(Task.URGENCY, Task.URGENCY_NONE); task.setValue(Task.DUE_DATE, 0L);
} }
task.setValue(Task.IMPORTANCE, rtmTask.getPriority().ordinal()); task.setValue(Task.IMPORTANCE, rtmTask.getPriority().ordinal());
} else { } else {
// error in upstream code, try to handle gracefully // error in upstream code, try to handle gracefully
Log.e("rtmsync", "Got null task parsing remote task series", Log.e("rtmsync", "Got null task parsing remote task series", //$NON-NLS-1$//$NON-NLS-2$
new Throwable()); new Throwable());
} }
@ -416,9 +415,9 @@ public class RTMSyncProvider extends SynchronizationProvider {
int length = tasks.size(); int length = tasks.size();
for(int i = 0; i < length; i++) { for(int i = 0; i < length; i++) {
Task task = tasks.get(i); Task task = tasks.get(i);
if(task.getValue(MilkDataService.LIST_ID).equals(target.getValue(MilkDataService.LIST_ID)) && if(task.getValue(MilkTask.LIST_ID).equals(target.getValue(MilkTask.LIST_ID)) &&
task.getValue(MilkDataService.TASK_SERIES_ID).equals(target.getValue(MilkDataService.TASK_SERIES_ID)) && task.getValue(MilkTask.TASK_SERIES_ID).equals(target.getValue(MilkTask.TASK_SERIES_ID)) &&
task.getValue(MilkDataService.TASK_ID).equals(target.getValue(MilkDataService.TASK_ID))) task.getValue(MilkTask.TASK_ID).equals(target.getValue(MilkTask.TASK_ID)))
return task; return task;
} }
return null; return null;
@ -426,7 +425,7 @@ public class RTMSyncProvider extends SynchronizationProvider {
@Override @Override
protected Task read(Task task) throws IOException { protected Task read(Task task) throws IOException {
RtmTaskSeries rtmTask = rtmService.tasks_getTask(task.getValue(MilkDataService.TASK_SERIES_ID), RtmTaskSeries rtmTask = rtmService.tasks_getTask(Long.toString(task.getValue(MilkTask.TASK_SERIES_ID)),
task.getValue(Task.TITLE)); task.getValue(Task.TITLE));
if(rtmTask != null) if(rtmTask != null)
return parseRemoteTask(rtmTask); return parseRemoteTask(rtmTask);
@ -435,25 +434,25 @@ public class RTMSyncProvider extends SynchronizationProvider {
@Override @Override
protected void transferIdentifiers(Task source, Task destination) { protected void transferIdentifiers(Task source, Task destination) {
destination.setValue(MilkDataService.LIST_ID, source.getValue(MilkDataService.LIST_ID)); destination.setValue(MilkTask.LIST_ID, source.getValue(MilkTask.LIST_ID));
destination.setValue(MilkDataService.TASK_SERIES_ID, source.getValue(MilkDataService.TASK_SERIES_ID)); destination.setValue(MilkTask.TASK_SERIES_ID, source.getValue(MilkTask.TASK_SERIES_ID));
destination.setValue(MilkDataService.TASK_ID, source.getValue(MilkDataService.TASK_ID)); destination.setValue(MilkTask.TASK_ID, source.getValue(MilkTask.TASK_ID));
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// ------------------------------------------------------- helper classes // ------------------------------------------------------- helper classes
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** Helper class for processing RTM id's into one field */ /** Helper class for storing RTM id's */
private static class RtmId { private static class RtmId {
public String taskId; public String taskId;
public String taskSeriesId; public String taskSeriesId;
public String listId; public String listId;
public RtmId(Task task) { public RtmId(Task task) {
taskId = task.getValue(MilkDataService.TASK_ID); taskId = Long.toString(task.getValue(MilkTask.TASK_ID));
taskSeriesId = task.getValue(MilkDataService.TASK_SERIES_ID); taskSeriesId = Long.toString(task.getValue(MilkTask.TASK_SERIES_ID));
listId = task.getValue(MilkDataService.LIST_ID); listId = Long.toString(task.getValue(MilkTask.LIST_ID));
} }
} }

@ -2,8 +2,8 @@ package com.todoroo.astrid.tags;
import java.util.ArrayList; import java.util.ArrayList;
import com.todoroo.andlib.data.Property.CountProperty;
import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.data.Property.CountProperty;
import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Criterion;
@ -43,11 +43,11 @@ public class TagService {
DependencyInjectionService.getInstance().inject(this); DependencyInjectionService.getInstance().inject(this);
} }
/** /**
* Property for retrieving count of aggregated rows * Property for retrieving count of aggregated rows
*/ */
private static final CountProperty COUNT = new CountProperty(); private static final CountProperty COUNT = new CountProperty();
public static final Order GROUPED_TAGS_BY_ALPHA = Order.asc(Metadata.VALUE); public static final Order GROUPED_TAGS_BY_ALPHA = Order.asc(Metadata.VALUE);
public static final Order GROUPED_TAGS_BY_SIZE = Order.desc(COUNT); public static final Order GROUPED_TAGS_BY_SIZE = Order.desc(COUNT);

@ -0,0 +1,22 @@
package com.todoroo.astrid.dao;
import com.todoroo.andlib.data.Property.IntegerProperty;
import com.todoroo.astrid.model.Metadata;
/**
* Helper class for representing string columns from joined metadata
*/
public class IntegerJoinProperty extends IntegerProperty implements JoinProperty {
public IntegerJoinProperty(String name) {
super(null, name);
}
@SuppressWarnings("nls")
public String joinTable() {
return String.format("SELECT %s,%s AS %s FROM %s WHERE %s='%s'",
Metadata.TASK, Metadata.VALUE, name,
Metadata.TABLE, Metadata.KEY, name);
}
}

@ -0,0 +1,14 @@
/**
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.dao;
public interface JoinProperty {
/**
* @return SQL select statement describing how to load this property
* in a join statement
*/
public String joinTable();
}

@ -0,0 +1,21 @@
package com.todoroo.astrid.dao;
import com.todoroo.andlib.data.Property.StringProperty;
import com.todoroo.astrid.model.Metadata;
/**
* Helper class for representing string columns from another table
*/
public class StringJoinProperty extends StringProperty implements JoinProperty {
public StringJoinProperty(String name) {
super(null, name);
}
@SuppressWarnings("nls")
public String joinTable() {
return String.format("SELECT %s,%s AS %s FROM %s WHERE %s='%s'",
Metadata.TASK, Metadata.VALUE, name,
Metadata.TABLE, Metadata.KEY, name);
}
}
Loading…
Cancel
Save