diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java index 5098dc7de..2c85c873f 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java @@ -230,55 +230,6 @@ public final class ActFmSyncService { } } - public void fetchFilterOrder(String localFilterId) { - if (!checkForToken()) - return; - - String filterId = SubtasksHelper.serverFilterOrderId(localFilterId); - ArrayList params = new ArrayList(); - params.add("filter"); params.add(filterId); - params.add("token"); params.add(token); - - try { - JSONObject result = actFmInvoker.invoke("list_order", params.toArray(new Object[params.size()])); - String order = result.optString("order"); - if (!TextUtils.isEmpty(order) && !"null".equals(order)) - Preferences.setString(localFilterId, SubtasksHelper.convertTreeToLocalIds(order)); - } catch (IOException e) { - handleException("fetch-filter-order", e); - } - } - - public void fetchTagOrder(TagData tagData) { - if (!checkForToken()) - return; - - if (!RemoteModel.isValidUuid(tagData.getUuid())) - return; - - try { - JSONObject result = actFmInvoker.invoke("list_order", "tag_id", tagData.getValue(TagData.UUID), "token", token); - JSONArray ordering = result.optJSONArray("order"); - if (ordering == null) - return; - if (ordering.optLong(0) != -1L) { - JSONArray newOrdering = new JSONArray(); - newOrdering.put(-1L); - for (int i = 0; i < ordering.length(); i++) - newOrdering.put(ordering.get(i)); - ordering = newOrdering; - } - String orderString = ordering.toString(); - String localOrder = SubtasksHelper.convertTreeToLocalIds(orderString); - tagData.setValue(TagData.TAG_ORDERING, localOrder); - tagDataService.save(tagData); - } catch (JSONException e) { - handleException("fetch-tag-order-json", e); - } catch (IOException e) { - handleException("fetch-tag-order-io", e); - } - } - // --- data fetch methods public int fetchFeaturedLists(int serverTime) throws JSONException, IOException { if (!checkForToken()) diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/AstridNewSyncMigrator.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/AstridNewSyncMigrator.java index 1675010e3..6230acd21 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/AstridNewSyncMigrator.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/AstridNewSyncMigrator.java @@ -46,6 +46,7 @@ import com.todoroo.astrid.files.FileMetadata; import com.todoroo.astrid.helper.UUIDHelper; import com.todoroo.astrid.service.MetadataService; import com.todoroo.astrid.service.TagDataService; +import com.todoroo.astrid.subtasks.SubtasksHelper; import com.todoroo.astrid.subtasks.SubtasksUpdater; import com.todoroo.astrid.tags.TaskToTagMetadata; @@ -310,6 +311,8 @@ public class AstridNewSyncMigrator { if (TextUtils.isEmpty(activeTasksOrder)) activeTasksOrder = "[]"; + activeTasksOrder = SubtasksHelper.convertTreeToRemoteIds(activeTasksOrder); + TaskListMetadata tlm = new TaskListMetadata(); tlm.setValue(TaskListMetadata.FILTER, TaskListMetadata.FILTER_ID_ALL); tlm.setValue(TaskListMetadata.TASK_IDS, activeTasksOrder); @@ -321,6 +324,8 @@ public class AstridNewSyncMigrator { if (TextUtils.isEmpty(todayTasksOrder)) todayTasksOrder = "[]"; + todayTasksOrder = SubtasksHelper.convertTreeToRemoteIds(todayTasksOrder); + tlm.setValue(TaskListMetadata.FILTER, TaskListMetadata.FILTER_ID_TODAY); tlm.setValue(TaskListMetadata.TASK_IDS, todayTasksOrder); tlm.putTransitory(SyncFlags.ACTFM_SUPPRESS_OUTSTANDING_ENTRIES, true); @@ -335,6 +340,8 @@ public class AstridNewSyncMigrator { td.readFromCursor(allTagData); String tagOrdering = td.getValue(TagData.TAG_ORDERING); + tagOrdering = SubtasksHelper.convertTreeToRemoteIds(tagOrdering); + tlm.setValue(TaskListMetadata.TASK_IDS, tagOrdering); tlm.setValue(TaskListMetadata.TAG_UUID, td.getUuid()); if (!tagsThatNeedOrderingSync.contains(td.getId())) diff --git a/astrid/plugin-src/com/todoroo/astrid/subtasks/AstridOrderedListFragmentHelper.java b/astrid/plugin-src/com/todoroo/astrid/subtasks/AstridOrderedListFragmentHelper.java index 85185c8f9..9ccd6b25b 100644 --- a/astrid/plugin-src/com/todoroo/astrid/subtasks/AstridOrderedListFragmentHelper.java +++ b/astrid/plugin-src/com/todoroo/astrid/subtasks/AstridOrderedListFragmentHelper.java @@ -232,22 +232,21 @@ public class AstridOrderedListFragmentHelper implements OrderedListFragmen } } - private final Map> chainedCompletions = - Collections.synchronizedMap(new HashMap>()); + private final Map> chainedCompletions = + Collections.synchronizedMap(new HashMap>()); private void setCompletedForItemAndSubtasks(final Task item, final boolean completedState) { - final long itemId = item.getId(); + final String itemId = item.getUuid(); final Task model = new Task(); final long completionDate = completedState ? DateUtilities.now() : 0; if(completedState == false) { - ArrayList chained = chainedCompletions.get(itemId); + ArrayList chained = chainedCompletions.get(itemId); if(chained != null) { - for(Long taskId : chained) { - model.setId(taskId); + for(String taskId : chained) { model.setValue(Task.COMPLETION_DATE, completionDate); - taskService.save(model); + taskService.update(Task.UUID.eq(taskId), model); model.clear(); taskAdapter.getCompletedItems().put(taskId, false); @@ -257,23 +256,23 @@ public class AstridOrderedListFragmentHelper implements OrderedListFragmen return; } - final ArrayList chained = new ArrayList(); + final ArrayList chained = new ArrayList(); updater.applyToDescendants(itemId, new AstridOrderedListUpdater.OrderedListNodeVisitor() { @Override public void visitNode(AstridOrderedListUpdater.Node node) { - model.setId(node.taskId); + String uuid = node.uuid; model.setValue(Task.COMPLETION_DATE, completionDate); - taskService.save(model); + taskService.update(Task.UUID.eq(uuid), model); model.clear(); - taskAdapter.getCompletedItems().put(node.taskId, true); - chained.add(node.taskId); + taskAdapter.getCompletedItems().put(node.uuid, true); + chained.add(node.uuid); } }); if(chained.size() > 0) { // move recurring items to item parent - TodorooCursor recurring = taskService.query(Query.select(Task.ID, Task.RECURRENCE).where( + TodorooCursor recurring = taskService.query(Query.select(Task.ID, Task.UUID, Task.RECURRENCE).where( Criterion.and(Task.ID.in(chained.toArray(new Long[chained.size()])), Task.RECURRENCE.isNotNull(), Functions.length(Task.RECURRENCE).gt(0)))); try { @@ -283,7 +282,7 @@ public class AstridOrderedListFragmentHelper implements OrderedListFragmen t.clear(); t.readFromCursor(recurring); if (!TextUtils.isEmpty(t.getValue(Task.RECURRENCE))) { - updater.moveToParentOf(t.getId(), itemId); + updater.moveToParentOf(t.getUuid(), itemId); madeChanges = true; } } @@ -311,14 +310,14 @@ public class AstridOrderedListFragmentHelper implements OrderedListFragmen } public void onCreateTask(Task task) { - updater.onCreateTask(list, getFilter(), task.getId()); + updater.onCreateTask(list, getFilter(), task.getUuid()); fragment.reconstructCursor(); fragment.loadTaskListContent(true); fragment.selectCustomId(task.getId()); } public void onDeleteTask(Task task) { - updater.onDeleteTask(list, getFilter(), task.getId()); + updater.onDeleteTask(list, getFilter(), task.getUuid()); taskAdapter.notifyDataSetInvalidated(); } diff --git a/astrid/plugin-src/com/todoroo/astrid/subtasks/AstridOrderedListUpdater.java b/astrid/plugin-src/com/todoroo/astrid/subtasks/AstridOrderedListUpdater.java index dba5d3501..4fba5cbe9 100644 --- a/astrid/plugin-src/com/todoroo/astrid/subtasks/AstridOrderedListUpdater.java +++ b/astrid/plugin-src/com/todoroo/astrid/subtasks/AstridOrderedListUpdater.java @@ -26,7 +26,7 @@ public abstract class AstridOrderedListUpdater { public AstridOrderedListUpdater() { DependencyInjectionService.getInstance().inject(this); - idToNode = new HashMap(); + idToNode = new HashMap(); } public interface OrderedListNodeVisitor { @@ -34,15 +34,16 @@ public abstract class AstridOrderedListUpdater { } public static class Node { - public long taskId; +// public long taskId; public String uuid; // For parsing and syncing -- not used elsewhere public Node parent; public int indent; public final ArrayList children = new ArrayList(); - public Node(long taskId, Node parent, int indent) { - this.taskId = taskId; - this.uuid = "-1"; //$NON-NLS-1$ + public Node(String uuid, Node parent, int indent) { +// this.taskId = taskId; + this.uuid = uuid; +// this.uuid = "-1"; //$NON-NLS-1$ this.parent = parent; this.indent = indent; } @@ -50,7 +51,7 @@ public abstract class AstridOrderedListUpdater { private Node treeRoot; - private final HashMap idToNode; + private final HashMap idToNode; protected abstract String getSerializedTree(LIST list, Filter filter); protected abstract void writeSerialization(LIST list, String serialized, boolean shouldQueueSync); @@ -71,7 +72,7 @@ public abstract class AstridOrderedListUpdater { treeRoot = buildTreeModel(serializedTree, new JSONTreeModelBuilder() { @Override public void afterAddNode(Node node) { - idToNode.put(node.taskId, node); + idToNode.put(node.uuid, node); } }); verifyTreeModel(list, filter); @@ -79,16 +80,16 @@ public abstract class AstridOrderedListUpdater { private void verifyTreeModel(LIST list, Filter filter) { boolean changedThings = false; - Set keySet = idToNode.keySet(); - Set currentIds = new HashSet(); - for (Long id : keySet) { + Set keySet = idToNode.keySet(); + Set currentIds = new HashSet(); + for (String id : keySet) { currentIds.add(id); } - Set idsInQuery = new HashSet(); - TodorooCursor tasks = taskService.fetchFiltered(filter.getSqlQuery(), null, Task.ID); + Set idsInQuery = new HashSet(); + TodorooCursor tasks = taskService.fetchFiltered(filter.getSqlQuery(), null, Task.UUID); try { for (tasks.moveToFirst(); !tasks.isAfterLast(); tasks.moveToNext()) { - Long id = tasks.getLong(0); + String id = tasks.getString(0); idsInQuery.add(id); if (idToNode.containsKey(id)) continue; @@ -111,8 +112,8 @@ public abstract class AstridOrderedListUpdater { writeSerialization(list, serializeTree(), false); } - private void removeNodes(Set idsToRemove) { - for (Long id : idsToRemove) { + private void removeNodes(Set idsToRemove) { + for (String id : idsToRemove) { Node node = idToNode.get(id); if (node == null) continue; @@ -132,39 +133,39 @@ public abstract class AstridOrderedListUpdater { return idToNode.get(taskId); } - public Long[] getOrderedIds() { - ArrayList ids = new ArrayList(); + private String[] getOrderedIds() { + ArrayList ids = new ArrayList(); orderedIdHelper(treeRoot, ids); - return ids.toArray(new Long[ids.size()]); + return ids.toArray(new String[ids.size()]); } public String getOrderString() { - Long[] ids = getOrderedIds(); + String[] ids = getOrderedIds(); return buildOrderString(ids); } - public static String buildOrderString(Long[] ids) { + public static String buildOrderString(String[] ids) { StringBuilder builder = new StringBuilder(); if (ids.length == 0) return "(1)"; //$NON-NLS-1$ for (int i = ids.length - 1; i >= 0; i--) { - builder.append(Task.ID.eq(ids[i]).toString()); + builder.append(Task.UUID.eq(ids[i]).toString()); if (i > 0) builder.append(", "); //$NON-NLS-1$ } return builder.toString(); } - private void orderedIdHelper(Node node, List ids) { + private void orderedIdHelper(Node node, List ids) { if (node != treeRoot) - ids.add(node.taskId); + ids.add(node.uuid); for (Node child : node.children) { orderedIdHelper(child, ids); } } - public void applyToDescendants(long taskId, OrderedListNodeVisitor visitor) { + public void applyToDescendants(String taskId, OrderedListNodeVisitor visitor) { Node n = idToNode.get(taskId); if (n == null) return; @@ -262,7 +263,7 @@ public abstract class AstridOrderedListUpdater { moveHelper(list, filter, target, before); } - public void moveToParentOf(long moveThis, long toParentOfThis) { + public void moveToParentOf(String moveThis, String toParentOfThis) { Node target = idToNode.get(toParentOfThis); if (target == null) return; @@ -328,18 +329,18 @@ public abstract class AstridOrderedListUpdater { applyToFilter(filter); } - public void onCreateTask(LIST list, Filter filter, long taskId) { - if (idToNode.containsKey(taskId) || taskId < 0) + public void onCreateTask(LIST list, Filter filter, String uuid) { + if (idToNode.containsKey(uuid) || !RemoteModel.isValidUuid(uuid)) return; - Node newNode = new Node(taskId, treeRoot, 0); + Node newNode = new Node(uuid, treeRoot, 0); treeRoot.children.add(newNode); - idToNode.put(taskId, newNode); + idToNode.put(uuid, newNode); writeSerialization(list, serializeTree(), true); applyToFilter(filter); } - public void onDeleteTask(LIST list, Filter filter, long taskId) { + public void onDeleteTask(LIST list, Filter filter, String taskId) { Node task = idToNode.get(taskId); if (task == null) return; @@ -367,41 +368,28 @@ public abstract class AstridOrderedListUpdater { } public static Node buildTreeModel(String serializedTree, JSONTreeModelBuilder callback) { - return buildTreeModel(serializedTree, callback, false); - } - public static Node buildTreeModel(String serializedTree, JSONTreeModelBuilder callback, boolean useUuid) { - Node root = new Node(-1, null, -1); + Node root = new Node("-1", null, -1); //$NON-NLS-1$ try { JSONArray tree = new JSONArray(serializedTree); - recursivelyBuildChildren(root, tree, callback, useUuid); + recursivelyBuildChildren(root, tree, callback); } catch (JSONException e) { Log.e("OrderedListUpdater", "Error building tree model", e); //$NON-NLS-1$//$NON-NLS-2$ } return root; } - private static void recursivelyBuildChildren(Node node, JSONArray children, JSONTreeModelBuilder callback, boolean useUuid) throws JSONException { + private static void recursivelyBuildChildren(Node node, JSONArray children, JSONTreeModelBuilder callback) throws JSONException { for (int i = 1; i < children.length(); i++) { JSONArray subarray = children.optJSONArray(i); - Long id = 0L; String uuid = RemoteModel.NO_UUID; - if (!useUuid) { - if (subarray == null) - id = children.getLong(i); - else - id = subarray.getLong(0); - } else { - if (subarray == null) - uuid = children.getString(i); - else - uuid = subarray.getString(0); - } + if (subarray == null) + uuid = children.getString(i); + else + uuid = subarray.getString(0); - Node child = new Node(id, node, node.indent + 1); - if (useUuid) - child.uuid = uuid; + Node child = new Node(uuid, node, node.indent + 1); if (subarray != null) - recursivelyBuildChildren(child, subarray, callback, useUuid); + recursivelyBuildChildren(child, subarray, callback); node.children.add(child); if (callback != null) callback.afterAddNode(child); @@ -409,43 +397,33 @@ public abstract class AstridOrderedListUpdater { } protected String serializeTree() { - return serializeTree(treeRoot, false); + return serializeTree(treeRoot); } public static String serializeTree(Node root) { - return serializeTree(root, false); - } - - public static String serializeTree(Node root, boolean useUuid) { JSONArray tree = new JSONArray(); if (root == null) { return tree.toString(); } try { - recursivelySerialize(root, tree, useUuid); + recursivelySerialize(root, tree); } catch (JSONException e) { Log.e("OrderedListUpdater", "Error serializing tree model", e); //$NON-NLS-1$//$NON-NLS-2$ } return tree.toString(); } - private static void recursivelySerialize(Node node, JSONArray serializeTo, boolean useUuid) throws JSONException { + private static void recursivelySerialize(Node node, JSONArray serializeTo) throws JSONException { ArrayList children = node.children; - if (useUuid) - serializeTo.put(node.uuid); - else - serializeTo.put(node.taskId); + serializeTo.put(node.uuid); for (Node child : children) { if (child.children.size() > 0) { JSONArray branch = new JSONArray(); - recursivelySerialize(child, branch, useUuid); + recursivelySerialize(child, branch); serializeTo.put(branch); } else { - if (useUuid) - serializeTo.put(child.uuid); - else - serializeTo.put(child.taskId); + serializeTo.put(child.uuid); } } } diff --git a/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksHelper.java b/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksHelper.java index 4da2c28de..15c0c4661 100644 --- a/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksHelper.java +++ b/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksHelper.java @@ -91,11 +91,12 @@ public class SubtasksHelper { else serialized = Preferences.getStringValue(SubtasksUpdater.ACTIVE_TASKS_ORDER); - return AstridOrderedListUpdater.buildOrderString(getIdArray(serialized)); + return AstridOrderedListUpdater.buildOrderString(getStringIdArray(serialized)); } @SuppressWarnings("nls") - public static Long[] getIdArray(String serializedTree) { + @Deprecated + private static Long[] getIdArray(String serializedTree) { ArrayList ids = new ArrayList(); String[] digitsOnly = serializedTree.split("[\\[\\],\\s]"); // Split on [ ] , or whitespace chars for (String idString : digitsOnly) { @@ -132,14 +133,19 @@ public class SubtasksHelper { Node tree = AstridOrderedListUpdater.buildTreeModel(localTree, null); remapLocalTreeToRemote(tree, idMap); - return AstridOrderedListUpdater.serializeTree(tree, true); + return AstridOrderedListUpdater.serializeTree(tree); } private static void remapLocalTreeToRemote(Node root, HashMap idMap) { ArrayList children = root.children; for (int i = 0; i < children.size(); i++) { Node child = children.get(i); - String uuid = idMap.get(child.taskId); + + long localId = -1L; + try { + localId = Long.parseLong(child.uuid); + } catch (NumberFormatException e) {/**/} + String uuid = idMap.get(localId); if (!RemoteModel.isValidUuid(uuid)) { children.remove(i); children.addAll(i, child.children); @@ -151,37 +157,6 @@ public class SubtasksHelper { } } - /** - * Takes a subtasks string containing UUIDs and remaps it to one containing local ids - * @param remoteTree - * @return - */ - public static String convertTreeToLocalIds(String remoteTree) { - String[] uuids = getStringIdArray(remoteTree); - HashMap idMap = getIdMap(uuids, Task.UUID, Task.ID); - idMap.put("-1", -1L); //$NON-NLS-1$ - - Node tree = AstridOrderedListUpdater.buildTreeModel(remoteTree, null, true); - remapRemoteTreeToLocal(tree, idMap); - return AstridOrderedListUpdater.serializeTree(tree); - } - - private static void remapRemoteTreeToLocal(Node root, HashMap idMap) { - ArrayList children = root.children; - for (int i = 0; i < children.size(); i++) { - Node child = children.get(i); - Long localId = idMap.get(child.uuid); - if (localId == null || localId <= 0) { - children.remove(i); - children.addAll(i, child.children); - i--; - } else { - child.taskId = localId; - remapRemoteTreeToLocal(child, idMap); - } - } - } - private static HashMap getIdMap(A[] keys, Property keyProperty, Property valueProperty) { HashMap map = new HashMap(); TodorooCursor tasks = PluginServices.getTaskService().query(Query.select(keyProperty, valueProperty).where(keyProperty.in(keys))); diff --git a/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksMetadataMigration.java b/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksMetadataMigration.java index 0675b995d..63d9272c0 100644 --- a/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksMetadataMigration.java +++ b/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksMetadataMigration.java @@ -93,7 +93,7 @@ public class SubtasksMetadataMigration { private String buildTreeModelFromMetadata(String tag, TodorooCursor cursor) { Metadata item = new Metadata(); - Node root = new Node(-1, null, -1); + Node root = new Node("-1", null, -1); //$NON-NLS-1$ for (; !cursor.isAfterLast(); cursor.moveToNext()) { item.clear(); item.readFromCursor(cursor); @@ -107,10 +107,10 @@ public class SubtasksMetadataMigration { indent = i.intValue(); } Node parent = findNextParentForIndent(root, indent); - Node newNode = new Node(item.getValue(Metadata.TASK), parent, parent.indent + 1); + Node newNode = new Node(item.getValue(Metadata.TASK).toString(), parent, parent.indent + 1); parent.children.add(newNode); } - return AstridOrderedListUpdater.serializeTree(root, false); + return AstridOrderedListUpdater.serializeTree(root); } private Node findNextParentForIndent(Node root, int indent) { diff --git a/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java b/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java index 27ec83dad..15f5ded9e 100644 --- a/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java +++ b/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java @@ -216,7 +216,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { protected final Context context; protected final TaskListFragment fragment; protected final Resources resources; - protected final HashMap completedItems = new HashMap(0); + protected final HashMap completedItems = new HashMap(0); protected OnCompletedTaskListener onCompletedTaskListener = null; public boolean isFling = false; protected final int resource; @@ -884,17 +884,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { startDetailThread(); } - /** - * Called to tell the cache to be cleared - */ - public void flushSpecific(long taskId) { - completedItems.put(taskId, null); - decorationManager.clearCache(taskId); - taskDetailLoader.remove(taskId); - taskActionLoader.remove(taskId); - } - - public HashMap getCompletedItems() { + public HashMap getCompletedItems() { return completedItems; } @@ -1075,7 +1065,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { if (activity == null) return; // show item as completed if it was recently checked - if(completedItems.get(task.getId()) != null) { + if(completedItems.get(task.getUuid()) != null || completedItems.get(task.getId()) != null) { task.setValue(Task.COMPLETION_DATE, completedItems.get(task.getId()) ? DateUtilities.now() : 0); } @@ -1252,7 +1242,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { if(onCompletedTaskListener != null) onCompletedTaskListener.onCompletedTask(task, newState); - completedItems.put(task.getId(), newState); + completedItems.put(task.getUuid(), newState); taskService.setComplete(task, newState); } }