class Table(ZopeDict): """ A table is a combination of a ZopeDict and a RepozeCatalog with integer keys and object values """ #TODO write my own IOBTree/Length combination instead of using ZopeDict? def __init__(self, parent, indices=None): ZopeDict.__init__(self) self.__parent__ = parent parent[self.__name__] = self self._cat = Catalog() if indices is None: self._currentIndex = "" else: self._currentIndex = indices[0] for index in indices: self._cat[index] = CatalogFieldIndex(index) def getCurrentIndex(self): # FIXME current index should be part of the user preferences return self._cat[self._currentIndex] def delete(self, names): print "TODO delete" pass def getFromIndex(self, index, target): # TODO return a generator instead of a list retval = [] result = self._cat.query(Eq(index, target)) for key in result[1]: user = self.get(key) if user: retval.append(user) return retval def maxKey(self): return self._data.maxKey() if len(self) else 0 # NB I have to cast key to an int for traversal to work # FIXME: it seems like this is the wrong place for this maybe it # is a sign I should give up on traversal altogether? def __getitem__(self, key): return self._data[int(key)] def setdefault(self, key, failobj=None): return ZopeDict.setdefault(self, int(key), failobj) def has_key(self, key): return ZopeDict.has_key(self, int(key)) def get(self, key, failobj=None): return ZopeDict.get(self, int(key), failobj) def __contains__(self, key): return ZopeDict.__contains__(self, int(key)) # zc.dict interface # Addition is done with __setitem__, overriding it will control addition. def __setitem__(self, key, value): #self._cat.index_doc(int(key), value) ZopeDict.__setitem__(self, int(key), value) #TODO find a way to do efficient automatic re-indexing # can't see that I can do better than Plone though # http://developer.plone.org/searching_and_indexing/indexing.html#when-indexing-happens-and-how-to-reindex-manually def reindex(self, value): self._cat.index_doc(value.key, value) # Removal is done with either pop or clear, overriding these methods will # control removal. def pop(self, key, *args): retval = ZopeDict.pop(self, int(key), *args) self._cat.unindex_doc(int(key)) return retval def clear(self): ZopeDict.clear(self) self._cat.clear()
def clear(self): """ Clear all indexes in this catalog. """ _Catalog.clear(self) self.objectids = self.family.IF.TreeSet()
class Table(ZopeDict): """ A table is a combination of a ZopeDict and a RepozeCatalog with integer keys and object values """ #TODO write my own IOBTree/Length combination instead of using ZopeDict? def __init__(self, parent, indices=None): ZopeDict.__init__(self) self.__parent__ = parent parent[self.__name__] = self self._cat = Catalog() if indices is None: self._currentIndex = "" else: self._currentIndex = indices[0] for index in indices: self._cat[index] = CatalogFieldIndex(index) def getCurrentIndex(self): # FIXME current index should be part of the user preferences return self._cat[self._currentIndex] def delete(self, names): print "TODO delete" pass def getFromIndex(self, index, target): # TODO return a generator instead of a list retval = [] result = self._cat.query(Eq(index, target)) for key in result[1]: user = self.get(key) if user: retval.append(user) return retval def maxKey(self): return self._data.maxKey() if len(self) else 0 # NB I have to cast key to an int for traversal to work # FIXME: it seems like this is the wrong place for this maybe it # is a sign I should give up on traversal altogether? def __getitem__(self, key): return self._data[int(key)] def setdefault(self, key, failobj=None): return ZopeDict.setdefault(self, int(key), failobj) def has_key(self, key): return ZopeDict.has_key(self, int(key)) def get(self, key, failobj=None): return ZopeDict.get(self, int(key), failobj) def __contains__(self, key): return ZopeDict.__contains__(self, int(key)) # zc.dict interface # Addition is done with __setitem__, overriding it will control addition. def __setitem__(self, key, value): #self._cat.index_doc(int(key), value) ZopeDict.__setitem__(self, int(key), value) #TODO find a way to do efficient automatic re-indexing # can't see that I can do better than Plone though # http://developer.plone.org/searching_and_indexing/indexing.html#when-indexing-happens-and-how-to-reindex-manually def reindex(self, value): self._cat.index_doc(value.key, value) # Removal is done with either pop or clear, overriding these methods will # control removal. def pop(self, key, *args): retval = ZopeDict.pop(self, int(key), *args) self._cat.unindex_doc(int(key)) return retval def clear(self): ZopeDict.clear(self) self._cat.clear()
class Catalog(object): def __init__(self): self._catalog = RepozeCatalog() self._document_map = DocumentMap() @property def catalog(self): """ convenient proxy to real catalog """ return self._catalog def query(self, qry, as_summary=False, as_object=False, **kwargs): """ Query the catalog. If as_summary is set, return object summaries, as fetched from info from the indexes""" res = self._catalog.query(qry, **kwargs) if as_summary: return [self.get_object_summary(uuid) for uuid in res[1]] elif as_object: return [self.get_object(uuid) for uuid in res[1]] else: return res def index_object(self, object): path = object_to_path(object) uuid = object.uuid docid = self._document_map.add(uuid) self._document_map.add_metadata(docid, {'path': path}) try: self.catalog.index_doc(docid, object) self._p_changed = 1 self.catalog._p_changed = 1 self._document_map._p_changed = 1 self.__parent__._p_changed = 1 except: LOGGER.exception("Could not index object!") def reindex_object(self, object): uuid = object.uuid docid = self._document_map.docid_for_address(uuid) if not docid: self.index_object(object) docid = self._document_map.docid_for_address(uuid) # update the path of the object in the documentmap since the # object might have been renamed / moved path = object_to_path(object) self._document_map.add_metadata(docid, {'path': path}) try: self.catalog.reindex_doc(docid, object) self._p_changed = 1 self.catalog._p_changed = 1 self._document_map._p_changed = 1 self.__parent__._p_changed = 1 except: LOGGER.exception("Could not index object!") def unindex_object(self, object): uuid = object.uuid docid = self._document_map.docid_for_address(uuid) if docid: self.catalog.unindex_doc(docid) self._document_map.remove_docid(docid) self._p_changed = 1 self.catalog._p_changed = 1 self._document_map._p_changed = 1 self.__parent__._p_changed = 1 def clear(self): self._catalog.clear() self._document_map = DocumentMap() self._p_changed = 1 self.catalog._p_changed = 1 self._document_map._p_changed = 1 self.__parent__._p_changed = 1 def get_object(self, docid): metadata = self._document_map.get_metadata(docid) path = metadata['path'] return path_to_object(path, self.__parent__) def get_object_summary(self, uuid): """ Return a summary of the found object, based on the values that the indexes hold on the given uuid""" summ = {} for key in self.catalog.keys(): idx = self.catalog[key] if hasattr(idx, "_rev_index"): summ[key] = idx._rev_index.get(uuid, '') summ['key'] = uuid return ObjectSummary(summ) def list_objects(self): docids = self.list_object_ids() for docid in docids: metadata = self._document_map.get_metadata(docid) yield (docid, metadata['path']) def list_object_ids(self): return self._document_map.docid_to_address.keys()