1bee9e8cf655dd9e4ffd07345eaf6a3679516164
[doneit] / src / cache_backend.py
1 class CacheBackend(object):
2
3         def __init__(self, backend):
4                 self._backend = backend
5                 self._projects = {}
6                 self._items = {}
7                 self._locations = {}
8                 self._taskIdToProjId = {}
9                 self._noteIdToTaskId = {}
10
11         def save(self):
12                 self._backend.save()
13
14         def load(self):
15                 self._backend.load()
16
17         def add_project(self, name):
18                 self._backend.add_project(name)
19                 self._invalidate_projects()
20
21         def set_project_name(self, projId, name):
22                 self._backend.set_project_name(projId, name)
23                 self._invalidate_projects()
24
25         def set_project_visibility(self, projId, visibility):
26                 self._backend.set_project_visibility(projId, visibility)
27                 self._invalidate_projects()
28
29         def get_projects(self):
30                 self._populate_projects()
31                 return self._projects.itervalues()
32
33         def get_project(self, projId):
34                 self._populate_projects()
35                 return self._projects[projId]
36
37         def lookup_project(self, projName):
38                 """
39                 From a project's name, returns the project's details
40                 """
41                 self._populate_projects()
42                 todoList = [
43                         projectDetails
44                         for projectDetails in self._projects.itervalues()
45                                 if projectDetails["name"] == projName
46                 ]
47                 assert len(todoList) == 1, "Wrong number of lists found for %s, in %r" % (projName, todoList)
48                 return todoList[0]
49
50         def get_locations(self):
51                 self._populate_locations()
52                 return self._locations.itervalues()
53
54         def get_tasks_with_details(self, projId):
55                 self._populate_tasks(projId)
56                 return self._items[projId].itervalues()
57
58         def get_task_details(self, taskId):
59                 projId = self._taskIdToProjId[taskId]
60                 self._populate_tasks(projId)
61                 return self._items[projId][taskId]
62
63         def add_task(self, projId, taskName):
64                 self._backend.add_task(projId, taskName)
65                 self._invalidate_projects_tasks(projId)
66                 self._invalidate_metaprojects_tasks()
67
68         def set_project(self, taskId, newProjId):
69                 self._backend.set_project(taskId, newProjId)
70                 projId = self._taskIdToProjId[taskId]
71                 self._invalidate_projects_tasks(projId)
72                 self._invalidate_projects_tasks(newProjId)
73                 self._invalidate_metaprojects_tasks()
74
75         def set_name(self, taskId, name):
76                 self._backend.set_name(taskId, name)
77                 self._invalidate_task(taskId)
78
79         def set_duedate(self, taskId, dueDate):
80                 self._backend.set_duedate(taskId, dueDate)
81                 self._invalidate_task(taskId)
82
83         def set_priority(self, taskId, priority):
84                 self._backend.set_priority(taskId, priority)
85                 self._invalidate_task(taskId)
86
87         def complete_task(self, taskId):
88                 self._backend.complete_task(taskId)
89                 self._invalidate_task(taskId)
90
91         def add_note(self, taskId, noteTitle, noteBody):
92                 self._backend.add_note(taskId, noteTitle, noteBody)
93                 self._invalidate_task(taskId)
94
95         def update_note(self, noteId, noteTitle, noteBody):
96                 self._backend.update_note(noteId, noteTitle, noteBody)
97                 taskId = self._noteIdToTaskId[noteId]
98                 self._invalidate_task(taskId)
99
100         def delete_note(self, noteId):
101                 self._backend.delete_note(noteId)
102                 taskId = self._noteIdToTaskId[noteId]
103                 del self._noteIdToTaskId[noteId]
104                 self._invalidate_task(taskId)
105
106         def _populate_projects(self):
107                 if self._projects:
108                         print "SAVED BY THE CACHE"
109                         return
110                 self._projects = dict((
111                         (proj["id"], proj)
112                         for proj in self._backend.get_projects()
113                 ))
114
115         def _populate_tasks(self, projId):
116                 if projId in self._items:
117                         print "SAVED BY THE CACHE"
118                         return
119                 self._items[projId] = dict((
120                         (task["id"], task)
121                         for task in self._backend.get_tasks_with_details(projId)
122                 ))
123                 for taskId, task in self._items[projId].iteritems():
124                         self._taskIdToProjId[taskId] = task["projId"]
125                         for noteId, note in task["notes"].iteritems():
126                                 self._noteIdToTaskId[noteId] = taskId
127
128         def _populate_locations(self):
129                 if self._locations:
130                         print "SAVED BY THE CACHE"
131                         return
132                 self._locations = dict((
133                         (loc["id"], loc)
134                         for loc in self._backend.get_locations()
135                 ))
136
137         def _invalidate_projects(self):
138                 self._projects.clear()
139
140         def _invalidate_task(self, taskId):
141                 projId = self._taskIdToProjId[taskId]
142                 self._invalidate_projects_tasks(projId)
143                 self._invalidate_metaprojects_tasks()
144
145         def _invalidate_projects_tasks(self, projId):
146                 del self._items[projId]
147
148         def _invalidate_metaprojects_tasks(self):
149                 for projId in self._get_metalists():
150                         self._invalidate_projects_tasks(projId)
151
152         def _get_metalists(self):
153                 return (
154                         list
155                         for list in self._projects.itervalues()
156                                 if not list["isMeta"]
157                 )