Added TODO and DEVELOPMENT.
[faces-project.git] / metapie / dbzope.py
blobd7e9fe455bb0e2348f44f5afdf25c7457af28385
1 ############################################################################
2 # Copyright (C) 2005 by Reithinger GmbH
3 # mreithinger@web.de
5 # This file is part of metapie.
6 #
7 # metapie is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # pyplan is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the
19 # Free Software Foundation, Inc.,
20 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 ############################################################################
24 """
25 DBObject for the ZODB
26 """
28 from ZODB import FileStorage, DB
29 from BTrees import OOBTree
30 from BTrees.IOBTree import IOBTree, multiunion
31 from BTrees.IFBTree import intersection
32 from BTrees.OIBTree import OIBTree
33 import BTrees.Length
34 import BTrees.IIBTree as iib
35 import transaction
36 import persistent
37 import metapie
38 import peer
39 import time
42 class Database(DB):
43 def __init__(self, storage, dbname="application"):
44 DB.__init__(self, storage)
45 self.connection = self.open()
46 dbroot = self.connection.root()
48 self.application = dbroot.setdefault(dbname, OOBTree.OOBTree())
49 IdGenerator.instance = dbroot.setdefault("ids", IdGenerator())
52 def make_entrance(self, entrance_class):
53 entrance = self.application.get("entrance", None)
54 if not entrance:
55 entrance = self.application["entrance"] = entrance_class()
56 transaction.commit()
58 entrance.set_instance()
59 return entrance
63 class FileDatabase(Database):
64 def __init__(self, filename, dbname="application"):
65 Database.__init__(self, FileStorage.FileStorage(filename), dbname)
68 class _ResultSet:
69 """Lazily accessed set of objects."""
71 def __init__(self, uids, uidutil):
72 self.uids = uids
73 self.uidutil = uidutil
76 def __len__(self):
77 return len(self.uids)
80 def __delitem__(self, imodel):
81 try:
82 self.uids.remove(imodel.id())
83 except AttributeError:
84 #make mutable
85 self.uids = multiunion(self.uids)
86 self.uids.remove(imodel.id())
89 def __getitem__(self, index):
90 return self.uidutil[self.uids[index]]
93 class SetContainer(object):
94 """
95 SetContainer is like a IITreeSet but
96 it support the operators & | -
97 """
99 def __init__(self, set):
100 self.set = iib.IISet(set)
102 def __and__(self, other):
103 return SetContainer(iib.intersection(self.set, other.set))
105 def __or__(self, other):
106 return SetContainer(iib.union(self.set, other.set))
108 def __sub__(self, other):
109 return SetContainer(iib.difference(self.set, other.set))
111 def __len__(self):
112 return len(self.set)
118 class Container(persistent.Persistent, peer.Peer):
119 def __init__(self, imodel, peer_class, name_to_me, name_to_peer, index):
120 self._container = IOBTree()
121 self._imodel = imodel
122 self._peer_class = peer_class
123 self._name_to_me = name_to_me
124 self._name_to_peer = name_to_peer
125 self._keys = {}
126 self._length = BTrees.Length.Length()
128 if index:
129 prop_to_attrib = dict(map(lambda kv: (kv[1]._get_value, kv[1]),
130 peer_class.__attributes_map__.iteritems()))
132 for attrib, index_type in index:
133 if isinstance(attrib, property):
134 attrib = prop_to_attrib[attrib.fget].name
136 self._keys[attrib] = index_type()
137 setattr(self, attrib, self._keys[attrib])
140 def check_peer(self, imodel):
141 if not isinstance(imodel, self._peer_class):
142 raise ValueError("'%s' is not of type '%s'"%
143 (str(obj), self.contained_class.__name__))
146 def fire(self):
147 self._imodel.fire(self._name_to_peer, self._name_to_peer)
148 self._imodel.fire("default", self._name_to_peer)
151 def insert(self, imodel, fire=True):
152 self.check_peer(imodel)
153 if self._insert_item(imodel):
154 self._add_to_peer(imodel, self._imodel)
155 if fire: self.fire()
158 def delete(self, imodel, fire=True):
159 if self._del_item(imodel):
160 self._remove_from_peer(imodel, self._imodel)
161 if fire: self.fire()
162 else:
163 raise KeyError("model does not exist in container", imodel)
166 def recatalog(self, obj):
167 if self._container.has_key(obj.id()):
168 self._remove_from_index(obj)
169 self._add_to_index(obj)
170 return True
172 return False
175 def sequence(self):
176 return _ResultSet(self._container.keys(), self._container)
179 def subset(self, idset):
180 try:
181 idset = idset.set
182 except ttributeError: pass
183 return _ResultSet(idset, self._container)
186 def __nonzero__(self): return self._length() > 0
187 def __len__(self): return self._length()
188 def __iter__(self): return self._container.itervalues()
189 def __contains__(self, y): return self._container.has_key(y.id())
190 def __getitem__(self, key): return self._container[key]
191 def __delitem__(self, imodel): self.delete(imodel)
194 def _insert_item(self, obj):
195 id_ = obj.id()
196 if self._container.has_key(id_):
197 return False
199 self._length.change(1)
200 self._container.insert(id_, obj)
201 self._add_to_index(obj)
202 return True
205 def _del_item(self, obj):
206 id_ = obj.id()
207 if not self._container.has_key(id_):
208 return False
210 self._length.change(-1)
211 del self._container[id_]
212 self._remove_from_index(obj)
213 return True
216 def _add_to_index(self, obj):
217 id_ = obj.id()
218 for k, v in self._keys.iteritems():
219 v.index_id(id_, getattr(obj, k))
222 def _remove_from_index(self, obj):
223 id_ = obj.id()
224 for v in self._keys.values():
225 v.unindex_id(id_)
228 class IdGenerator(persistent.Persistent):
229 instance = None
231 def get_id(cls, type="default"):
232 if not cls.instance: cls.instance = cls()
234 counter = getattr(cls.instance, type, 0)
235 setattr(cls.instance, type, counter + 1)
236 transaction.commit()
237 return counter
239 get_id = classmethod(get_id)
243 class _PersistentBase(persistent.Persistent, object):
244 __id_type__ = None
246 def __init__(self):
247 #generate a unique long lasting id
248 self.__id = IdGenerator.get_id(self.__id_type__ \
249 or self.__class__.__name__)
250 #self.__id = int(time.time()) % 100000 + (id(self) % 10000) * 100000
253 def id(self): return self.__id
255 metapie._init_db_module("zodb", _PersistentBase, Container, transaction.commit)
257 from dblayout import *