diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksIndentAction.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksIndentAction.java index c866bdef2..6c4a8a366 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksIndentAction.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksIndentAction.java @@ -22,6 +22,7 @@ import com.todoroo.astrid.utility.Flags; abstract public class GtasksIndentAction extends BroadcastReceiver { @Autowired private GtasksMetadataService gtasksMetadataService; + @Autowired private GtasksTaskListUpdater gtasksTaskListUpdater; abstract int getDelta(); @@ -43,7 +44,7 @@ abstract public class GtasksIndentAction extends BroadcastReceiver { metadata.setValue(GtasksMetadata.INDENT, newIndent); PluginServices.getMetadataService().save(metadata); - gtasksMetadataService.updateMetadataForList(metadata.getValue(GtasksMetadata.LIST_ID)); + gtasksTaskListUpdater.updateMetadataForList(metadata.getValue(GtasksMetadata.LIST_ID)); Flags.set(Flags.REFRESH); Toast.makeText(context, context.getString(R.string.gtasks_indent_toast, newIndent), diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksMetadataService.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksMetadataService.java index 752d7fc88..8652761dc 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksMetadataService.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksMetadataService.java @@ -4,21 +4,13 @@ package com.todoroo.astrid.gtasks; import java.util.ArrayList; -import java.util.HashMap; -import java.util.Stack; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.sql.Criterion; -import com.todoroo.astrid.api.Filter; -import com.todoroo.astrid.core.PluginServices; import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria; import com.todoroo.astrid.data.Metadata; -import com.todoroo.astrid.data.StoreObject; import com.todoroo.astrid.data.Task; import com.todoroo.astrid.gtasks.sync.GtasksTaskContainer; import com.todoroo.astrid.sync.SyncMetadataService; @@ -33,7 +25,6 @@ import com.todoroo.astrid.sync.SyncProviderUtilities; public final class GtasksMetadataService extends SyncMetadataService { @Autowired private GtasksPreferenceService gtasksPreferenceService; - @Autowired private GtasksListService gtasksListService; public GtasksMetadataService() { super(ContextManager.getContext()); @@ -66,113 +57,4 @@ public final class GtasksMetadataService extends SyncMetadataService ids = new ArrayList(); - final Stack taskHierarchyStack = new Stack(); - - final AtomicInteger order = new AtomicInteger(0); - final AtomicInteger previousIndent = new AtomicInteger(-1); - - iterateThroughList(list, new ListIterator() { - @Override - public void processTask(long taskId) { - ids.add(taskId); - Metadata metadata = getTaskMetadata(taskId); - if(metadata == null) - return; - - metadata.setValue(GtasksMetadata.ORDER, order.getAndAdd(1)); - int indent = metadata.getValue(GtasksMetadata.INDENT); - - for(int i = indent; i <= previousIndent.get(); i++) { - if(!taskHierarchyStack.isEmpty()) - taskHierarchyStack.pop(); - } - - if(indent > 0) { - if(taskHierarchyStack.isEmpty()) { - metadata.setValue(GtasksMetadata.PARENT_TASK, 0L); - metadata.setValue(GtasksMetadata.INDENT, 0); - } else - metadata.setValue(GtasksMetadata.PARENT_TASK, taskHierarchyStack.peek()); - } else { - metadata.setValue(GtasksMetadata.PARENT_TASK, 0L); - } - - PluginServices.getMetadataService().save(metadata); - taskHierarchyStack.push(taskId); - previousIndent.set(indent); - } - }); - - PluginServices.getTaskService().clearDetails(Task.ID.in(ids)); - } - - /** - * Create a local tree of tasks to expedite sibling and parent lookups - */ - public void createParentSiblingMaps() { - final HashMap parents = new HashMap(); - final HashMap siblings = new HashMap(); - - for(StoreObject list : gtasksListService.getLists()) { - final AtomicLong previousTask = new AtomicLong(-1L); - final AtomicInteger previousIndent = new AtomicInteger(-1); - - iterateThroughList(list, new ListIterator() { - @Override - public void processTask(long taskId) { - Metadata metadata = getTaskMetadata(taskId); - if(metadata == null) - return; - - int indent = metadata.getValue(GtasksMetadata.INDENT); - - final long parent, sibling; - if(indent > previousIndent.get()) { - parent = previousTask.get(); - sibling = -1L; - } else if(indent == previousIndent.get()) { - sibling = previousTask.get(); - parent = parents.get(sibling); - } else { - sibling = parents.get(previousTask.get()); - parent = parents.get(sibling); - } - parents.put(taskId, parent); - siblings.put(taskId, sibling); - - previousTask.set(taskId); - previousIndent.set(indent); - } - }); - } - } - - private interface ListIterator { - public void processTask(long taskId); - } - - private void iterateThroughList(StoreObject list, ListIterator iterator) { - Filter filter = GtasksFilterExposer.filterFromList(list); - TodorooCursor cursor = PluginServices.getTaskService().fetchFiltered(filter.sqlQuery, null, Task.ID); - try { - for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { - long taskId = cursor.getLong(0); - iterator.processTask(taskId); - } - - } finally { - cursor.close(); - } - } - } diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksOrderAction.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksOrderAction.java index 6194f996d..115f961da 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksOrderAction.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksOrderAction.java @@ -23,6 +23,7 @@ import com.todoroo.astrid.utility.Flags; abstract public class GtasksOrderAction extends BroadcastReceiver { @Autowired private GtasksMetadataService gtasksMetadataService; + @Autowired private GtasksTaskListUpdater gtasksTaskListUpdater; abstract int getDelta(); @@ -38,7 +39,7 @@ abstract public class GtasksOrderAction extends BroadcastReceiver { if(metadata == null) return; - gtasksMetadataService.updateMetadataForList(metadata.getValue(GtasksMetadata.LIST_ID)); + gtasksTaskListUpdater.updateMetadataForList(metadata.getValue(GtasksMetadata.LIST_ID)); metadata = gtasksMetadataService.getTaskMetadata(taskId); int oldOrder = metadata.getValue(GtasksMetadata.ORDER); diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksTaskListUpdater.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksTaskListUpdater.java new file mode 100644 index 000000000..d6b269096 --- /dev/null +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksTaskListUpdater.java @@ -0,0 +1,142 @@ +package com.todoroo.astrid.gtasks; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Stack; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import android.text.TextUtils; + +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.core.PluginServices; +import com.todoroo.astrid.data.Metadata; +import com.todoroo.astrid.data.StoreObject; +import com.todoroo.astrid.data.Task; + +public class GtasksTaskListUpdater { + + @Autowired private GtasksListService gtasksListService; + @Autowired private GtasksMetadataService gtasksMetadataService; + + private final HashMap parents = new HashMap(); + private final HashMap siblings = new HashMap(); + private final HashMap localToRemoteIdMap = + new HashMap(); + + public GtasksTaskListUpdater() { + DependencyInjectionService.getInstance().inject(this); + } + + /** + * Update order and parent fields for all tasks in the given list + * @param listId + */ + public void updateMetadataForList(String listId) { + StoreObject list = gtasksListService.getList(listId); + if(list == GtasksListService.LIST_NOT_FOUND_OBJECT) + return; + + final ArrayList ids = new ArrayList(); + final Stack taskHierarchyStack = new Stack(); + + final AtomicInteger order = new AtomicInteger(0); + final AtomicInteger previousIndent = new AtomicInteger(-1); + + iterateThroughList(list, new ListIterator() { + @Override + public void processTask(long taskId) { + ids.add(taskId); + Metadata metadata = gtasksMetadataService.getTaskMetadata(taskId); + if(metadata == null) + return; + + metadata.setValue(GtasksMetadata.ORDER, order.getAndAdd(1)); + int indent = metadata.getValue(GtasksMetadata.INDENT); + + for(int i = indent; i <= previousIndent.get(); i++) { + if(!taskHierarchyStack.isEmpty()) + taskHierarchyStack.pop(); + } + + if(indent > 0) { + if(taskHierarchyStack.isEmpty()) { + metadata.setValue(GtasksMetadata.PARENT_TASK, 0L); + metadata.setValue(GtasksMetadata.INDENT, 0); + } else + metadata.setValue(GtasksMetadata.PARENT_TASK, taskHierarchyStack.peek()); + } else { + metadata.setValue(GtasksMetadata.PARENT_TASK, 0L); + } + + PluginServices.getMetadataService().save(metadata); + taskHierarchyStack.push(taskId); + previousIndent.set(indent); + } + }); + + PluginServices.getTaskService().clearDetails(Task.ID.in(ids)); + } + + /** + * Create a local tree of tasks to expedite sibling and parent lookups + */ + public void createParentSiblingMaps() { + for(StoreObject list : gtasksListService.getLists()) { + final AtomicLong previousTask = new AtomicLong(-1L); + final AtomicInteger previousIndent = new AtomicInteger(-1); + + iterateThroughList(list, new ListIterator() { + @Override + public void processTask(long taskId) { + Metadata metadata = gtasksMetadataService.getTaskMetadata(taskId); + if(metadata == null) + return; + + int indent = metadata.getValue(GtasksMetadata.INDENT); + + final long parent, sibling; + if(indent > previousIndent.get()) { + parent = previousTask.get(); + sibling = -1L; + } else if(indent == previousIndent.get()) { + sibling = previousTask.get(); + parent = parents.get(sibling); + } else { + sibling = parents.get(previousTask.get()); + parent = parents.get(sibling); + } + parents.put(taskId, parent); + siblings.put(taskId, sibling); + + previousTask.set(taskId); + previousIndent.set(indent); + if(!TextUtils.isEmpty(metadata.getValue(GtasksMetadata.ID))) + localToRemoteIdMap.put(taskId, metadata.getValue(GtasksMetadata.ID)); + } + }); + } + } + + private interface ListIterator { + public void processTask(long taskId); + } + + private void iterateThroughList(StoreObject list, ListIterator iterator) { + Filter filter = GtasksFilterExposer.filterFromList(list); + TodorooCursor cursor = PluginServices.getTaskService().fetchFiltered(filter.sqlQuery, null, Task.ID); + try { + for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { + long taskId = cursor.getLong(0); + iterator.processTask(taskId); + } + + } finally { + cursor.close(); + } + } +} + diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncProvider.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncProvider.java index 05599f991..ae80504ff 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncProvider.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncProvider.java @@ -38,6 +38,7 @@ import com.todoroo.astrid.gtasks.GtasksMetadata; import com.todoroo.astrid.gtasks.GtasksMetadataService; import com.todoroo.astrid.gtasks.GtasksPreferenceService; import com.todoroo.astrid.gtasks.GtasksPreferences; +import com.todoroo.astrid.gtasks.GtasksTaskListUpdater; import com.todoroo.astrid.producteev.ProducteevBackgroundService; import com.todoroo.astrid.producteev.ProducteevLoginActivity; import com.todoroo.astrid.producteev.ProducteevUtilities; @@ -66,6 +67,7 @@ public class GtasksSyncProvider extends SyncProvider { @Autowired private GtasksListService gtasksListService; @Autowired private GtasksMetadataService gtasksMetadataService; @Autowired private GtasksPreferenceService gtasksPreferenceService; + @Autowired private GtasksTaskListUpdater gtasksTaskListUpdater; /** google task service fields */ private GoogleTaskService taskService = null; @@ -214,7 +216,7 @@ public class GtasksSyncProvider extends SyncProvider { gtasksListService.updateLists(taskView.getAllLists()); - gtasksMetadataService.createParentSiblingMaps(); + gtasksTaskListUpdater.createParentSiblingMaps(); // batched read tasks for each list ArrayList remoteTasks = new ArrayList(); diff --git a/astrid/src/com/todoroo/astrid/service/AstridDependencyInjector.java b/astrid/src/com/todoroo/astrid/service/AstridDependencyInjector.java index f95c02d42..b4e14f5fd 100644 --- a/astrid/src/com/todoroo/astrid/service/AstridDependencyInjector.java +++ b/astrid/src/com/todoroo/astrid/service/AstridDependencyInjector.java @@ -14,6 +14,7 @@ import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.gtasks.GtasksListService; import com.todoroo.astrid.gtasks.GtasksMetadataService; import com.todoroo.astrid.gtasks.GtasksPreferenceService; +import com.todoroo.astrid.gtasks.GtasksTaskListUpdater; import com.todoroo.astrid.utility.Constants; /** @@ -68,6 +69,7 @@ public class AstridDependencyInjector extends AbstractDependencyInjector { injectables.put("gtasksPreferenceService", GtasksPreferenceService.class); injectables.put("gtasksListService", GtasksListService.class); injectables.put("gtasksMetadataService", GtasksMetadataService.class); + injectables.put("gtasksTaskListUpdater", GtasksTaskListUpdater.class); // these make reference to fields defined above injectables.put("errorReporters", new ErrorReporter[] {