Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/creactistore/_templates/lib/rdflib/plugins/memory.py
diff options
context:
space:
mode:
Diffstat (limited to 'creactistore/_templates/lib/rdflib/plugins/memory.py')
-rw-r--r--creactistore/_templates/lib/rdflib/plugins/memory.py563
1 files changed, 563 insertions, 0 deletions
diff --git a/creactistore/_templates/lib/rdflib/plugins/memory.py b/creactistore/_templates/lib/rdflib/plugins/memory.py
new file mode 100644
index 0000000..3a9d9f8
--- /dev/null
+++ b/creactistore/_templates/lib/rdflib/plugins/memory.py
@@ -0,0 +1,563 @@
+from __future__ import generators
+from rdflib.term import BNode
+from rdflib.store import Store, NO_STORE, VALID_STORE
+
+__all__ = ['Memory', 'IOMemory']
+
+ANY = Any = None
+
+class Memory(Store):
+ """\
+ An in memory implementation of a triple store.
+
+ This triple store uses nested dictionaries to store triples. Each
+ triple is stored in two such indices as follows spo[s][p][o] = 1 and
+ pos[p][o][s] = 1.
+
+ Authors: Michel Pelletier, Daniel Krech, Stefan Niederhauser
+ """
+ def __init__(self, configuration=None, identifier=None):
+ super(Memory, self).__init__(configuration)
+ self.identifier = identifier
+
+ # indexed by [subject][predicate][object]
+ self.__spo = {}
+
+ # indexed by [predicate][object][subject]
+ self.__pos = {}
+
+ # indexed by [predicate][object][subject]
+ self.__osp = {}
+
+ self.__namespace = {}
+ self.__prefix = {}
+
+ def add(self, (subject, predicate, object), context, quoted=False):
+ """\
+ Add a triple to the store of triples.
+ """
+ # add dictionary entries for spo[s][p][p] = 1 and pos[p][o][s]
+ # = 1, creating the nested dictionaries where they do not yet
+ # exits.
+ spo = self.__spo
+ try:
+ po = spo[subject]
+ except:
+ po = spo[subject] = {}
+ try:
+ o = po[predicate]
+ except:
+ o = po[predicate] = {}
+ o[object] = 1
+
+ pos = self.__pos
+ try:
+ os = pos[predicate]
+ except:
+ os = pos[predicate] = {}
+ try:
+ s = os[object]
+ except:
+ s = os[object] = {}
+ s[subject] = 1
+
+ osp = self.__osp
+ try:
+ sp = osp[object]
+ except:
+ sp = osp[object] = {}
+ try:
+ p = sp[subject]
+ except:
+ p = sp[subject] = {}
+ p[predicate] = 1
+
+ def remove(self, (subject, predicate, object), context=None):
+ for (subject, predicate, object), c in self.triples(
+ (subject, predicate, object)):
+ del self.__spo[subject][predicate][object]
+ del self.__pos[predicate][object][subject]
+ del self.__osp[object][subject][predicate]
+
+ def triples(self, (subject, predicate, object), context=None):
+ """A generator over all the triples matching """
+ if subject!=ANY: # subject is given
+ spo = self.__spo
+ if subject in spo:
+ subjectDictionary = spo[subject]
+ if predicate!=ANY: # subject+predicate is given
+ if predicate in subjectDictionary:
+ if object!=ANY: # subject+predicate+object is given
+ if object in subjectDictionary[predicate]:
+ yield (subject, predicate, object), \
+ self.__contexts()
+ else: # given object not found
+ pass
+ else: # subject+predicate is given, object unbound
+ for o in subjectDictionary[predicate].keys():
+ yield (subject, predicate, o), \
+ self.__contexts()
+ else: # given predicate not found
+ pass
+ else: # subject given, predicate unbound
+ for p in subjectDictionary.keys():
+ if object!=ANY: # object is given
+ if object in subjectDictionary[p]:
+ yield (subject, p, object), self.__contexts()
+ else: # given object not found
+ pass
+ else: # object unbound
+ for o in subjectDictionary[p].keys():
+ yield (subject, p, o), self.__contexts()
+ else: # given subject not found
+ pass
+ elif predicate!=ANY: # predicate is given, subject unbound
+ pos = self.__pos
+ if predicate in pos:
+ predicateDictionary = pos[predicate]
+ if object!=ANY: # predicate+object is given, subject unbound
+ if object in predicateDictionary:
+ for s in predicateDictionary[object].keys():
+ yield (s, predicate, object), self.__contexts()
+ else: # given object not found
+ pass
+ else: # predicate is given, object+subject unbound
+ for o in predicateDictionary.keys():
+ for s in predicateDictionary[o].keys():
+ yield (s, predicate, o), self.__contexts()
+ elif object!=ANY: # object is given, subject+predicate unbound
+ osp = self.__osp
+ if object in osp:
+ objectDictionary = osp[object]
+ for s in objectDictionary.keys():
+ for p in objectDictionary[s].keys():
+ yield (s, p, object), self.__contexts()
+ else: # subject+predicate+object unbound
+ spo = self.__spo
+ for s in spo.keys():
+ subjectDictionary = spo[s]
+ for p in subjectDictionary.keys():
+ for o in subjectDictionary[p].keys():
+ yield (s, p, o), self.__contexts()
+
+ def __len__(self, context=None):
+ #@@ optimize
+ i = 0
+ for triple in self.triples((None, None, None)):
+ i += 1
+ return i
+
+ def bind(self, prefix, namespace):
+ self.__prefix[namespace] = prefix
+ self.__namespace[prefix] = namespace
+
+ def namespace(self, prefix):
+ return self.__namespace.get(prefix, None)
+
+ def prefix(self, namespace):
+ return self.__prefix.get(namespace, None)
+
+ def namespaces(self):
+ for prefix, namespace in self.__namespace.iteritems():
+ yield prefix, namespace
+
+ def __contexts(self):
+ return (c for c in []) # TODO: best way to return empty generator
+
+class IOMemory(Store):
+ """\
+ An integer-key-optimized-context-aware-in-memory store.
+
+ Uses nested dictionaries to store triples and context. Each triple
+ is stored in six such indices as follows cspo[c][s][p][o] = 1
+ and cpos[c][p][o][s] = 1 and cosp[c][o][s][p] = 1 as well as
+ spo[s][p][o] = [c] and pos[p][o][s] = [c] and pos[o][s][p] = [c]
+
+ Context information is used to track the 'source' of the triple
+ data for merging, unmerging, remerging purposes. context aware
+ store stores consume more memory size than non context stores.
+
+ """
+
+ context_aware = True
+ formula_aware = True
+
+ def __init__(self, configuration=None, identifier=None):
+ super(IOMemory, self).__init__()
+
+ # indexed by [context][subject][predicate][object] = 1
+ self.cspo = self.createIndex()
+
+ # indexed by [context][predicate][object][subject] = 1
+ self.cpos = self.createIndex()
+
+ # indexed by [context][object][subject][predicate] = 1
+ self.cosp = self.createIndex()
+
+ # indexed by [subject][predicate][object] = [context]
+ self.spo = self.createIndex()
+
+ # indexed by [predicate][object][subject] = [context]
+ self.pos = self.createIndex()
+
+ # indexed by [object][subject][predicate] = [context]
+ self.osp = self.createIndex()
+
+ # indexes integer keys to identifiers
+ self.forward = self.createForward()
+
+ # reverse index of forward
+ self.reverse = self.createReverse()
+
+ self.identifier = identifier or BNode()
+
+ self.__namespace = self.createPrefixMap()
+ self.__prefix = self.createPrefixMap()
+
+ def open(self, configuration, create=False):
+ if not create:
+ # An IOMemory Store never exists.
+ return NO_STORE
+ else:
+ return VALID_STORE
+
+ def bind(self, prefix, namespace):
+ self.__prefix[namespace] = prefix
+ self.__namespace[prefix] = namespace
+
+ def namespace(self, prefix):
+ return self.__namespace.get(prefix, None)
+
+ def prefix(self, namespace):
+ return self.__prefix.get(namespace, None)
+
+ def namespaces(self):
+ for prefix, namespace in self.__namespace.iteritems():
+ yield prefix, namespace
+
+ def defaultContext(self):
+ return self.default_context
+
+ def addContext(self, context):
+ """ Add context w/o adding statement. Dan you can remove this if you want """
+
+ if not self.reverse.has_key(context):
+ ci=randid()
+ while not self.forward.insert(ci, context):
+ ci=randid()
+ self.reverse[context] = ci
+
+ def intToIdentifier(self, (si, pi, oi)):
+ """ Resolve an integer triple into identifers. """
+ return (self.forward[si], self.forward[pi], self.forward[oi])
+
+ def identifierToInt(self, (s, p, o)):
+ """ Resolve an identifier triple into integers. """
+ return (self.reverse[s], self.reverse[p], self.reverse[o])
+
+ def uniqueSubjects(self, context=None):
+ if context is None:
+ index = self.spo
+ else:
+ index = self.cspo[context]
+ for si in index.keys():
+ yield self.forward[si]
+
+ def uniquePredicates(self, context=None):
+ if context is None:
+ index = self.pos
+ else:
+ index = self.cpos[context]
+ for pi in index.keys():
+ yield self.forward[pi]
+
+ def uniqueObjects(self, context=None):
+ if context is None:
+ index = self.osp
+ else:
+ index = self.cosp[context]
+ for oi in index.keys():
+ yield self.forward[oi]
+
+ def createForward(self):
+ return {}
+
+ def createReverse(self):
+ return {}
+
+ def createIndex(self):
+ return {}
+
+ def createPrefixMap(self):
+ return {}
+
+ def add(self, triple, context, quoted=False):
+ """\
+ Add a triple to the store.
+ """
+ Store.add(self, triple, context, quoted)
+ for triple, cg in self.triples(triple, context):
+ #triple is already in the store.
+ return
+
+ subject, predicate, object = triple
+
+ f = self.forward
+ r = self.reverse
+
+ # assign keys for new identifiers
+
+ if not r.has_key(subject):
+ si=randid()
+ while f.has_key(si):
+ si=randid()
+ f[si] = subject
+ r[subject] = si
+ else:
+ si = r[subject]
+
+ if not r.has_key(predicate):
+ pi=randid()
+ while f.has_key(pi):
+ pi=randid()
+ f[pi] = predicate
+ r[predicate] = pi
+ else:
+ pi = r[predicate]
+
+ if not r.has_key(object):
+ oi=randid()
+ while f.has_key(oi):
+ oi=randid()
+ f[oi] = object
+ r[object] = oi
+ else:
+ oi = r[object]
+
+ if not r.has_key(context):
+ ci=randid()
+ while f.has_key(ci):
+ ci=randid()
+ f[ci] = context
+ r[context] = ci
+ else:
+ ci = r[context]
+
+ # add dictionary entries for cspo[c][s][p][o] = 1,
+ # cpos[c][p][o][s] = 1, and cosp[c][o][s][p] = 1, creating the
+ # nested {} where they do not yet exits.
+ self._setNestedIndex(self.cspo, ci, si, pi, oi)
+ self._setNestedIndex(self.cpos, ci, pi, oi, si)
+ self._setNestedIndex(self.cosp, ci, oi, si, pi)
+
+ if not quoted:
+ self._setNestedIndex(self.spo, si, pi, oi, ci)
+ self._setNestedIndex(self.pos, pi, oi, si, ci)
+ self._setNestedIndex(self.osp, oi, si, pi, ci)
+
+ def _setNestedIndex(self, index, *keys):
+ for key in keys[:-1]:
+ if not index.has_key(key):
+ index[key] = self.createIndex()
+ index = index[key]
+ index[keys[-1]] = 1
+
+
+ def _removeNestedIndex(self, index, *keys):
+ """ Remove context from the list of contexts in a nested index.
+
+ Afterwards, recursively remove nested indexes when they became empty.
+ """
+ parents = []
+ for key in keys[:-1]:
+ parents.append(index)
+ index = index[key]
+ del index[keys[-1]]
+
+ n = len(parents)
+ for i in xrange(n):
+ index = parents[n-1-i]
+ key = keys[n-1-i]
+ if len(index[key]) == 0:
+ del index[key]
+
+ def remove(self, triple, context=None):
+ Store.remove(self, triple, context)
+ if context is not None:
+ if context == self:
+ context = None
+
+ f = self.forward
+ r = self.reverse
+ if context is None:
+ for triple, cg in self.triples(triple):
+ subject, predicate, object = triple
+ si, pi, oi = self.identifierToInt((subject, predicate, object))
+ contexts = list(self.contexts(triple))
+ for context in contexts:
+ ci = r[context]
+ del self.cspo[ci][si][pi][oi]
+ del self.cpos[ci][pi][oi][si]
+ del self.cosp[ci][oi][si][pi]
+
+ self._removeNestedIndex(self.spo, si, pi, oi, ci)
+ self._removeNestedIndex(self.pos, pi, oi, si, ci)
+ self._removeNestedIndex(self.osp, oi, si, pi, ci)
+ # grr!! hafta ref-count these before you can collect them dumbass!
+ #del f[si], f[pi], f[oi]
+ #del r[subject], r[predicate], r[object]
+ else:
+ subject, predicate, object = triple
+ ci = r.get(context, None)
+ if ci:
+ for triple, cg in self.triples(triple, context):
+ si, pi, oi = self.identifierToInt(triple)
+ del self.cspo[ci][si][pi][oi]
+ del self.cpos[ci][pi][oi][si]
+ del self.cosp[ci][oi][si][pi]
+
+ try:
+ self._removeNestedIndex(self.spo, si, pi, oi, ci)
+ self._removeNestedIndex(self.pos, pi, oi, si, ci)
+ self._removeNestedIndex(self.osp, oi, si, pi, ci)
+ except KeyError:
+ # the context may be a quoted one in which
+ # there will not be a triple in spo, pos or
+ # osp. So ignore any KeyErrors
+ pass
+ # TODO delete references to resources in self.forward/self.reverse
+ # that are not in use anymore...
+
+ if subject is None and predicate is None and object is None:
+ # remove context
+ try:
+ ci = self.reverse[context]
+ del self.cspo[ci], self.cpos[ci], self.cosp[ci]
+ except KeyError:
+ # TODO: no exception when removing non-existant context?
+ pass
+
+
+ def triples(self, triple, context=None):
+ """A generator over all the triples matching """
+
+ if context is not None:
+ if context == self:
+ context = None
+
+ subject, predicate, object = triple
+ ci = si = pi = oi = Any
+
+ if context is None:
+ spo = self.spo
+ pos = self.pos
+ osp = self.osp
+ else:
+ try:
+ ci = self.reverse[context] # TODO: Really ignore keyerror here
+ spo = self.cspo[ci]
+ pos = self.cpos[ci]
+ osp = self.cosp[ci]
+ except KeyError:
+ return
+ try:
+ if subject is not Any:
+ si = self.reverse[subject] # throws keyerror if subject doesn't exist ;(
+ if predicate is not Any:
+ pi = self.reverse[predicate]
+ if object is not Any:
+ oi = self.reverse[object]
+ except KeyError, e:
+ return #raise StopIteration
+
+ if si != Any: # subject is given
+ if spo.has_key(si):
+ subjectDictionary = spo[si]
+ if pi != Any: # subject+predicate is given
+ if subjectDictionary.has_key(pi):
+ if oi!= Any: # subject+predicate+object is given
+ if subjectDictionary[pi].has_key(oi):
+ ss, pp, oo = self.intToIdentifier((si, pi, oi))
+ yield (ss, pp, oo), (c for c in self.contexts((ss, pp, oo)))
+ else: # given object not found
+ pass
+ else: # subject+predicate is given, object unbound
+ for o in subjectDictionary[pi].keys():
+ ss, pp, oo = self.intToIdentifier((si, pi, o))
+ yield (ss, pp, oo), (c for c in self.contexts((ss, pp, oo)))
+ else: # given predicate not found
+ pass
+ else: # subject given, predicate unbound
+ for p in subjectDictionary.keys():
+ if oi != Any: # object is given
+ if subjectDictionary[p].has_key(oi):
+ ss, pp, oo = self.intToIdentifier((si, p, oi))
+ yield (ss, pp, oo), (c for c in self.contexts((ss, pp, oo)))
+ else: # given object not found
+ pass
+ else: # object unbound
+ for o in subjectDictionary[p].keys():
+ ss, pp, oo = self.intToIdentifier((si, p, o))
+ yield (ss, pp, oo), (c for c in self.contexts((ss, pp, oo)))
+ else: # given subject not found
+ pass
+ elif pi != Any: # predicate is given, subject unbound
+ if pos.has_key(pi):
+ predicateDictionary = pos[pi]
+ if oi != Any: # predicate+object is given, subject unbound
+ if predicateDictionary.has_key(oi):
+ for s in predicateDictionary[oi].keys():
+ ss, pp, oo = self.intToIdentifier((s, pi, oi))
+ yield (ss, pp, oo), (c for c in self.contexts((ss, pp, oo)))
+ else: # given object not found
+ pass
+ else: # predicate is given, object+subject unbound
+ for o in predicateDictionary.keys():
+ for s in predicateDictionary[o].keys():
+ ss, pp, oo = self.intToIdentifier((s, pi, o))
+ yield (ss, pp, oo), (c for c in self.contexts((ss, pp, oo)))
+ elif oi != Any: # object is given, subject+predicate unbound
+ if osp.has_key(oi):
+ objectDictionary = osp[oi]
+ for s in objectDictionary.keys():
+ for p in objectDictionary[s].keys():
+ ss, pp, oo = self.intToIdentifier((s, p, oi))
+ yield (ss, pp, oo), (c for c in self.contexts((ss, pp, oo)))
+ else: # subject+predicate+object unbound
+ for s in spo.keys():
+ subjectDictionary = spo[s]
+ for p in subjectDictionary.keys():
+ for o in subjectDictionary[p].keys():
+ ss, pp, oo = self.intToIdentifier((s, p, o))
+ yield (ss, pp, oo), (c for c in self.contexts((ss, pp, oo)))
+
+ def __len__(self, context=None):
+
+ if context is not None:
+ if context == self:
+ context = None
+
+ # TODO: for eff. implementation
+ count = 0
+ for triple, cg in self.triples((Any, Any, Any), context):
+ count += 1
+ return count
+
+ def contexts(self, triple=None):
+ if triple:
+ si, pi, oi = self.identifierToInt(triple)
+ for ci in self.spo[si][pi][oi]:
+ yield self.forward[ci]
+ else:
+ for ci in self.cspo.keys():
+ yield self.forward[ci]
+
+
+
+
+import random
+
+def randid(randint=random.randint, choice=random.choice, signs=(-1,1)):
+ return choice(signs)*randint(1,2000000000)
+
+del random