--- /dev/null
+class CacheBackend(object):
+
+ def __init__(self, backend):
+ self._backend = backend
+ self._projects = {}
+ self._items = {}
+ self._locations = {}
+ self._taskIdToProjId = {}
+ self._noteIdToTaskId = {}
+
+ def save(self):
+ self._backend.save()
+
+ def load(self):
+ self._backend.load()
+
+ def add_project(self, name):
+ self._backend.add_project(name)
+ self._invalidate_projects()
+
+ def set_project_name(self, projId, name):
+ self._backend.set_project_name(projId, name)
+ self._invalidate_projects()
+
+ def set_project_visibility(self, projId, visibility):
+ self._backend.set_project_visibility(projId, visibility)
+ self._invalidate_projects()
+
+ def get_projects(self):
+ self._populate_projects()
+ return self._projects.itervalues()
+
+ def get_project(self, projId):
+ self._populate_projects()
+ return self._projects[projId]
+
+ def lookup_project(self, projName):
+ """
+ From a project's name, returns the project's details
+ """
+ self._populate_projects()
+ todoList = [
+ projectDetails
+ for projectDetails in self._projects.itervalues()
+ if projectDetails["name"] == projName
+ ]
+ assert len(todoList) == 1, "Wrong number of lists found for %s, in %r" % (projName, todoList)
+ return todoList[0]
+
+ def get_locations(self):
+ self._populate_locations()
+ return self._locations.itervalues()
+
+ def get_tasks_with_details(self, projId):
+ self._populate_tasks(projId)
+ return self._items[projId]
+
+ def get_task_details(self, taskId):
+ projId = self._taskIdToProjId[taskId]
+ self._populate_tasks(projId)
+ return self._items[projId][taskId]
+
+ def add_task(self, projId, taskName):
+ self._backend.add_task(projId, taskName)
+ self._invalidate_projects_tasks(projId)
+ self._invalidate_metaprojects_tasks()
+
+ def set_project(self, taskId, newProjId):
+ self._backend.set_project(taskId, newProjId)
+ projId = self._taskIdToProjId[taskId]
+ self._invalidate_projects_tasks(projId)
+ self._invalidate_projects_tasks(newProjId)
+ self._invalidate_metaprojects_tasks()
+
+ def set_name(self, taskId, name):
+ self._backend.set_name(taskId, name)
+ self._invalidate_task(taskId)
+
+ def set_duedate(self, taskId, dueDate):
+ self._backend.set_duedate(taskId, dueDate)
+ self._invalidate_task(taskId)
+
+ def set_priority(self, taskId, priority):
+ self._backend.set_priority(taskId, priority)
+ self._invalidate_task(taskId)
+
+ def complete_task(self, taskId):
+ self._backend.complete_task(taskId)
+ self._invalidate_task(taskId)
+
+ def add_note(self, taskId, noteTitle, noteBody):
+ self._backend.add_note(taskId, noteTitle, noteBody)
+ self._invalidate_task(taskId)
+
+ def update_note(self, noteId, noteTitle, noteBody):
+ self._backend.update_note(noteId, noteTitle, noteBody)
+ taskId = self._noteIdToTaskId[noteId]
+ self._invalidate_task(taskId)
+
+ def delete_note(self, noteId):
+ self._backend.delete_note(noteId)
+ taskId = self._noteIdToTaskId[noteId]
+ del self._noteIdToTaskId[noteId]
+ self._invalidate_task(taskId)
+
+ def _populate_projects(self):
+ if self._projects:
+ return
+ self._projects = dict((
+ (proj["id"], proj)
+ for proj in self._backend.get_projects()
+ ))
+
+ def _populate_tasks(self, projId):
+ if projId in self._items:
+ return
+ self._items[projId] = dict((
+ (task["id"], task)
+ for task in self.get_tasks_with_details(projId)
+ ))
+ for taskId, task in self._items[projId].iteritems():
+ self._taskIdToProjId[taskId] = task["projId"]
+ for noteId, note in task.notes.iteritems():
+ self._noteIdToTaskId[noteId] = taskId
+
+ def _populate_locations(self):
+ if self._locations:
+ return
+ self._locations = dict((
+ (loc["id"], loc)
+ for loc in self._backend.get_locations()
+ ))
+
+ def _invalidate_projects(self):
+ self._projects.clear()
+
+ def _invalidate_task(self, taskId):
+ projId = self._taskIdToProjId[taskId]
+ self._invalidate_projects_tasks(projId)
+ self._invalidate_metaprojects_tasks()
+
+ def _invalidate_projects_tasks(self, projId):
+ del self._items[projId]
+
+ def _invalidate_metaprojects_tasks(self):
+ for projId in self._get_metalists():
+ self._invalidate_projects_tasks(projId)
+
+ def _get_metalists(self):
+ return (
+ list
+ for list in self._projects.itervalues()
+ if not list["isMeta"]
+ )