Fixed subtasks type parsing and conversion between local and remote trees. Should have the correct helpers now when we start syncing subtasks under sync v2

pull/14/head
Sam Bosley 12 years ago
parent 95af2428ef
commit ac0a1eda07

@ -15,6 +15,7 @@ import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.data.RemoteModel;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.TaskService;
@ -34,12 +35,14 @@ public abstract class AstridOrderedListUpdater<LIST> {
public static class Node {
public long taskId;
public String uuid; // For parsing and syncing -- not used elsewhere
public Node parent;
public int indent;
public final ArrayList<Node> children = new ArrayList<Node>();
public Node(long taskId, Node parent, int indent) {
this.taskId = taskId;
this.uuid = RemoteModel.NO_UUID;
this.parent = parent;
this.indent = indent;
}
@ -364,28 +367,41 @@ public abstract class AstridOrderedListUpdater<LIST> {
}
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);
try {
JSONArray tree = new JSONArray(serializedTree);
recursivelyBuildChildren(root, tree, callback);
recursivelyBuildChildren(root, tree, callback, useUuid);
} 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) throws JSONException {
private static void recursivelyBuildChildren(Node node, JSONArray children, JSONTreeModelBuilder callback, boolean useUuid) throws JSONException {
for (int i = 1; i < children.length(); i++) {
JSONArray subarray = children.optJSONArray(i);
Long id;
if (subarray == null)
id = children.getLong(i);
else
id = subarray.getLong(0);
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);
}
Node child = new Node(id, node, node.indent + 1);
if (useUuid)
child.uuid = uuid;
if (subarray != null)
recursivelyBuildChildren(child, subarray, callback);
recursivelyBuildChildren(child, subarray, callback, useUuid);
node.children.add(child);
if (callback != null)
callback.afterAddNode(child);
@ -393,30 +409,37 @@ public abstract class AstridOrderedListUpdater<LIST> {
}
protected String serializeTree() {
return serializeTree(treeRoot);
return serializeTree(treeRoot, false);
}
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);
recursivelySerialize(root, tree, useUuid);
} 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) throws JSONException {
private static void recursivelySerialize(Node node, JSONArray serializeTo, boolean useUuid) throws JSONException {
ArrayList<Node> children = node.children;
serializeTo.put(node.taskId);
if (useUuid)
serializeTo.put(node.uuid);
else
serializeTo.put(node.taskId);
for (Node child : children) {
if (child.children.size() > 0) {
JSONArray branch = new JSONArray();
recursivelySerialize(child, branch);
recursivelySerialize(child, branch, useUuid);
serializeTo.put(branch);
} else {
serializeTo.put(child.taskId);

@ -7,6 +7,7 @@ import android.content.SharedPreferences;
import android.text.TextUtils;
import android.util.Log;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.sql.Criterion;
@ -20,6 +21,7 @@ import com.todoroo.astrid.core.CustomFilterExposer;
import com.todoroo.astrid.core.PluginServices;
import com.todoroo.astrid.core.SortHelper;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
import com.todoroo.astrid.data.RemoteModel;
import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.subtasks.AstridOrderedListUpdater.Node;
@ -107,68 +109,87 @@ public class SubtasksHelper {
return ids.toArray(new Long[ids.size()]);
}
@SuppressWarnings("nls")
public static String[] getStringIdArray(String serializedTree) {
ArrayList<String> ids = new ArrayList<String>();
String[] values = serializedTree.split("[\\[\\],\\s]"); // Split on [ ] , or whitespace chars
for (String idString : values) {
if (!TextUtils.isEmpty(idString))
ids.add(idString);
}
return ids.toArray(new String[ids.size()]);
}
/**
* Takes a subtasks string containing local ids and remaps it to one containing UUIDs
* @param localTree
* @return
*/
public static String convertTreeToRemoteIds(String localTree) {
return convertIdTree(localTree, true);
Long[] localIds = getIdArray(localTree);
HashMap<Long, String> idMap = getIdMap(localIds, Task.ID, Task.UUID);
idMap.put(-1L, "-1"); //$NON-NLS-1$
Node tree = AstridOrderedListUpdater.buildTreeModel(localTree, null);
remapLocalTreeToRemote(tree, idMap);
return AstridOrderedListUpdater.serializeTree(tree, true);
}
public static String convertTreeToLocalIds(String remoteTree) {
return convertIdTree(remoteTree, false);
private static void remapLocalTreeToRemote(Node root, HashMap<Long, String> idMap) {
ArrayList<Node> children = root.children;
for (int i = 0; i < children.size(); i++) {
Node child = children.get(i);
String uuid = idMap.get(child.taskId);
if (!RemoteModel.isValidUuid(uuid)) {
children.remove(i);
children.addAll(i, child.children);
i--;
} else {
child.uuid = uuid;
remapLocalTreeToRemote(child, idMap);
}
}
}
private static String convertIdTree(String treeString, boolean localToRemote) {
Long[] ids = getIdArray(treeString);
HashMap<Long, Long> idMap = buildIdMap(ids, localToRemote);
idMap.put(-1L, -1L);
/**
* 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<String, Long> idMap = getIdMap(uuids, Task.UUID, Task.ID);
idMap.put("-1", -1L); //$NON-NLS-1$
Node tree = AstridOrderedListUpdater.buildTreeModel(treeString, null);
remapTree(tree, idMap);
Node tree = AstridOrderedListUpdater.buildTreeModel(remoteTree, null, true);
remapRemoteTreeToLocal(tree, idMap);
return AstridOrderedListUpdater.serializeTree(tree);
}
private static void remapTree(Node root, HashMap<Long, Long> idMap) {
private static void remapRemoteTreeToLocal(Node root, HashMap<String, Long> idMap) {
ArrayList<Node> 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) {
Long localId = idMap.get(child.uuid);
if (localId == null || localId <= 0) {
children.remove(i);
children.addAll(i, child.children);
i--;
} else {
child.taskId = remoteId;
remapTree(child, idMap);
child.taskId = localId;
remapRemoteTreeToLocal(child, idMap);
}
}
}
private static HashMap<Long, Long> buildIdMap(Long[] localIds, boolean localToRemote) { // If localToRemote is true, keys are local ids. If false. keys are remtoe ids
HashMap<Long, Long> map = new HashMap<Long, Long>();
Criterion criterion;
if (localToRemote)
criterion = Task.ID.in(localIds);
else
criterion = Task.UUID.in(localIds);
TodorooCursor<Task> tasks = PluginServices.getTaskService().query(Query.select(Task.ID, Task.UUID).where(criterion));
private static <A, B> HashMap<A, B> getIdMap(A[] keys, Property<A> keyProperty, Property<B> valueProperty) {
HashMap<A, B> map = new HashMap<A, B>();
TodorooCursor<Task> tasks = PluginServices.getTaskService().query(Query.select(keyProperty, valueProperty).where(keyProperty.in(keys)));
try {
Task t = new Task();
for (tasks.moveToFirst(); !tasks.isAfterLast(); tasks.moveToNext()) {
t.clear();
t.readFromCursor(tasks);
if (t.containsNonNullValue(Task.UUID)) {
Long key;
Long value;
if (localToRemote) {
key = t.getId();
value = Long.parseLong(t.getValue(Task.UUID));
} else {
key = Long.parseLong(t.getValue(Task.UUID));
value = t.getId();
}
map.put(key, value);
}
A key = tasks.get(keyProperty);
B value = tasks.get(valueProperty);
map.put(key, value);
}
} finally {
tasks.close();

@ -110,7 +110,7 @@ public class SubtasksMetadataMigration {
Node newNode = new Node(item.getValue(Metadata.TASK), parent, parent.indent + 1);
parent.children.add(newNode);
}
return AstridOrderedListUpdater.serializeTree(root);
return AstridOrderedListUpdater.serializeTree(root, false);
}
private Node findNextParentForIndent(Node root, int indent) {

Loading…
Cancel
Save