From 7130547bef8719feac159e26359707f070348f27 Mon Sep 17 00:00:00 2001 From: Sam Bosley Date: Fri, 2 Nov 2012 16:55:06 -0700 Subject: [PATCH] Wrote some helper functions to convert subtask trees between local and remote ids (could be useful for syncing) --- .../subtasks/AstridOrderedListUpdater.java | 35 ++++++--- .../astrid/subtasks/SubtasksHelper.java | 78 ++++++++++++++++++- 2 files changed, 99 insertions(+), 14 deletions(-) diff --git a/astrid/plugin-src/com/todoroo/astrid/subtasks/AstridOrderedListUpdater.java b/astrid/plugin-src/com/todoroo/astrid/subtasks/AstridOrderedListUpdater.java index d8cf84285..0974ccca1 100644 --- a/astrid/plugin-src/com/todoroo/astrid/subtasks/AstridOrderedListUpdater.java +++ b/astrid/plugin-src/com/todoroo/astrid/subtasks/AstridOrderedListUpdater.java @@ -31,7 +31,7 @@ public abstract class AstridOrderedListUpdater { } public static class Node { - public final long taskId; + public long taskId; public Node parent; public int indent; public final ArrayList children = new ArrayList(); @@ -63,7 +63,12 @@ public abstract class AstridOrderedListUpdater { } public void initializeFromSerializedTree(LIST list, Filter filter, String serializedTree) { - treeRoot = buildTreeModel(serializedTree); + treeRoot = buildTreeModel(serializedTree, new JSONTreeModelBuilder() { + @Override + public void afterAddNode(Node node) { + idToNode.put(node.taskId, node); + } + }); verifyTreeModel(list, filter); } @@ -303,44 +308,54 @@ public abstract class AstridOrderedListUpdater { applyToFilter(filter); } - private Node buildTreeModel(String serializedTree) { + private interface JSONTreeModelBuilder { + void afterAddNode(Node node); + } + + public static Node buildTreeModel(String serializedTree, JSONTreeModelBuilder callback) { Node root = new Node(-1, null, -1); try { JSONArray tree = new JSONArray(serializedTree); - recursivelyBuildChildren(root, tree); + recursivelyBuildChildren(root, tree, callback); } catch (JSONException e) { Log.e("OrderedListUpdater", "Error building tree model", e); //$NON-NLS-1$//$NON-NLS-2$ } return root; } - private void recursivelyBuildChildren(Node node, JSONArray children) 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); if (subarray == null) { Long id = children.getLong(i); Node child = new Node(id, node, node.indent + 1); node.children.add(child); - idToNode.put(id, child); + if (callback != null) + callback.afterAddNode(child); } else { Long id = subarray.getLong(0); Node child = new Node(id, node, node.indent + 1); - recursivelyBuildChildren(child, subarray); + recursivelyBuildChildren(child, subarray, callback); node.children.add(child); - idToNode.put(id, child); + if (callback != null) + callback.afterAddNode(child); } } } protected String serializeTree() { + return serializeTree(treeRoot); + } + + public static String serializeTree(Node root) { JSONArray tree = new JSONArray(); - if (treeRoot == null) { + if (root == null) { return tree.toString(); } try { tree.put(-1L); - recursivelySerialize(treeRoot, tree); + recursivelySerialize(root, tree); } catch (JSONException e) { Log.e("OrderedListUpdater", "Error serializing tree model", e); //$NON-NLS-1$//$NON-NLS-2$ } diff --git a/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksHelper.java b/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksHelper.java index ba5c063cc..fbff4cc2c 100644 --- a/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksHelper.java +++ b/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksHelper.java @@ -1,13 +1,16 @@ package com.todoroo.astrid.subtasks; import java.util.ArrayList; +import java.util.HashMap; import android.content.SharedPreferences; import android.text.TextUtils; import android.util.Log; +import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.sql.Criterion; +import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.utility.Preferences; import com.todoroo.astrid.actfm.TagViewFragment; import com.todoroo.astrid.api.Filter; @@ -18,6 +21,7 @@ import com.todoroo.astrid.core.SortHelper; import com.todoroo.astrid.dao.TaskDao.TaskCriteria; import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.Task; +import com.todoroo.astrid.subtasks.AstridOrderedListUpdater.Node; import com.todoroo.astrid.utility.AstridPreferences; public class SubtasksHelper { @@ -75,12 +79,11 @@ public class SubtasksHelper { else serialized = Preferences.getStringValue(SubtasksUpdater.ACTIVE_TASKS_ORDER); - ArrayList ids = getIdArray(serialized); - return AstridOrderedListUpdater.buildOrderString(ids.toArray(new Long[ids.size()])); + return AstridOrderedListUpdater.buildOrderString(getIdArray(serialized)); } @SuppressWarnings("nls") - private static ArrayList getIdArray(String serializedTree) { + public static Long[] getIdArray(String serializedTree) { ArrayList ids = new ArrayList(); String[] digitsOnly = serializedTree.split("\\D+"); for (String idString : digitsOnly) { @@ -91,7 +94,74 @@ public class SubtasksHelper { Log.e("widget-subtasks", "error parsing id " + idString, e); } } - return ids; + return ids.toArray(new Long[ids.size()]); + } + + public static String convertTreeToRemoteIds(String localTree) { + return convertIdTree(localTree, true); + } + + public static String convertTreeToLocalIds(String remoteTree) { + return convertIdTree(remoteTree, false); + } + + private static String convertIdTree(String treeString, boolean localToRemote) { + Long[] ids = getIdArray(treeString); + HashMap idMap = buildIdMap(ids, localToRemote); + + Node tree = AstridOrderedListUpdater.buildTreeModel(treeString, null); + remapTree(tree, idMap); + return AstridOrderedListUpdater.serializeTree(tree); + } + + private static void remapTree(Node root, HashMap idMap) { + ArrayList children = root.children; + for (int i = 0; i < children.size(); i++) { + Node child = children.get(i); + Long remoteId = idMap.get(child.taskId); + if (remoteId == null || remoteId <= 0) { + children.remove(i); + i--; + } else { + child.taskId = remoteId; + remapTree(child, idMap); + } + } + } + + private static HashMap buildIdMap(Long[] localIds, boolean localToRemote) { // If localToRemote is true, keys are local ids. If false. keys are remtoe ids + HashMap map = new HashMap(); + Criterion criterion; + if (localToRemote) + criterion = Task.ID.in(localIds); + else + criterion = Task.REMOTE_ID.in(localIds); + + TodorooCursor tasks = PluginServices.getTaskService().query(Query.select(Task.ID, Task.REMOTE_ID).where(criterion)); + try { + Task t = new Task(); + for (tasks.moveToFirst(); !tasks.isAfterLast(); tasks.moveToNext()) { + t.clear(); + t.readFromCursor(tasks); + + if (t.containsNonNullValue(Task.REMOTE_ID)) { + Long key; + Long value; + if (localToRemote) { + key = t.getId(); + value = t.getValue(Task.REMOTE_ID); + } else { + key = t.getValue(Task.REMOTE_ID); + value = t.getId(); + } + + map.put(key, value); + } + } + } finally { + tasks.close(); + } + return map; } }