#!/usr/bin/python """Semantic Web API""" __author__ = 'Sean B. Palmer' __license__ = 'Copyright (C) 2002 Sean B. Palmer. GNU GPL 2' SUBJECT, PREDICATE, OBJECT, FORMULA = 0, 1, 2, 3 class Article: """This is the main kind of "thing" in the API.""" def __init__(self, s): s, self.__r = str(s), str(s) if s[0] == '"': self.value, self.type = s[1:-1], 'Literal' elif s[0] == '?': self.value, self.type = s[1:], 'Univar' elif s[0] == '_': self.value, self.type = s[2:], 'Exivar' elif s[0] == '<': self.value, self.type = s[1:-1], 'URI' else: self.value, self.type, self.__r = s, 'URI', '<%s>' % s def __repr__(self): return self.__r def __eq__(self, x): return `self` == `x` def set(self, s): self.__init__(s) class Tuple(tuple): """This is basically an n-ary association of Articles.""" def __eq__(self, x): if not isinstance(x, Tuple): return 0 elif not (len(self) == len(x)): return 0 else: return `self` == `x` class Triple(Tuple): def __init__(self, data): assert (len(data) == 3) # check that it's a triple tuple.__init__(self, data) def __repr__(self): return 'Triple'+Tuple.__repr__(self) def __eq__(self, x): if not isinstance(x, Triple): return 0 elif not (len(x) == 3): return 0 else: return `self` == `x` class TupleStore(list): """This is a kind of list of tuples.""" def __init__(self, data=None): list.__init__(self) self._tuples = [] self._vars = [] self._counter = 1 if data: self.extend(data) def feed(self, store): varmap = {} for t in store: t = t[:] for i in range(len(t)): if t[i].type[-3:] == 'var': ti = `t[i]` if ti in varmap.keys(): t[i] = varmap[ti] else: while `t[i]` in self._vars: t[i] = Article(`t[i]` + `self._counter`) self._counter += 1 varmap[ti] = t[i] self.append(t) def query(self, q, loose=1): r = [] for t in self: # Query the triple against the store if len(t) != len(q): pass else: add = 1 for i in range(len(t)): if loose: if (q[i].type[-3:] != 'var') and (`t[i]` != `q[i]`): add = 0 else: if (q[i].type != 'Univar') and (`t[i]` != `q[i]`): add = 0 if add: r.append(t) return r def remove(self, t, loose=1): q = self.query(t, loose) return TupleStore(filter(lambda x: (x not in q), self)) class TripleStore(TupleStore): def __init__(self, data=None): list.__init__(self) self._striples = {} self._triples = {} self._tuples = [] self._vars = [] self._counter = 1 if data: self.extend(data) def _triplesAppend(self, t): self._striplesAppend(t) self._ptriplesAppend(t) def _striplesAppend(self, (s, p, o)): s, p, o = (`s`, `p`, `o`) try: if o not in self._striples[s][p]: self._striples[s][p] += [o] except: try: self._striples[s][p] = [o] except: self._striples[s] = { p: [o] } def _ptriplesAppend(self, t): s, p, o = (`t[0]`, `t[1]`, `t[2]`) try: if o not in self._triples[p][s]: self._triples[p][s] += [o] TupleStore.append(self, t) except: try: self._triples[p][s] = [o] TupleStore.append(self, t) except: self._triples[p] = { s: [o] } TupleStore.append(self, t) def append(self, t): """Append the triple t to the store if it does not already contain it.""" assert isinstance(t, Triple) for b in t: if b.type[-3:] == 'var': self._vars.append(`b`) self._triplesAppend(t) def extend(self, *triplelists): for triplelist in triplelists: for triple in triplelist: self.append(triple) def query(self, q, loose=1): var, r = [('Univar',), ('Univar', 'Exivar')][loose], [] s, p, o = (`q[0]`, `q[1]`, `q[2]`) if q[0].type not in var: # the subject is ground if q[1].type not in var: if q[2].type not in var: # xxx if o in self._striples[s][p]: return q else: return [] else: # xx? try: return [Triple((q[0], q[1], Article(t))) for t in self._striples[s][p]] except: return [] else: if q[2].type not in var: # x?x if s in self._striples.keys(): for predicate in self._striples[s]: if o in self._striples[s][predicate]: r.append(Triples((q[0], Article(predicate), q[2]))) return r else: return [] else: # x?? if s in self._striples.keys(): for predicate in self._striples[s].keys(): for object in self._striples[s][predicate]: r.append( Triple((q[0], Article(predicate), Article(object))) ) else: return [] else: # ?-- if q[1].type not in var: # ?x- if q[2].type not in var: # ?xx. the unknown subject: difficult if p in self._triples.keys(): for subject in self._triples[p]: if o in self._triples[p][subject]: r.append(Triple((Article(subject), q[1], q[2]))) return r else: return [] else: # ?x? if p in self._triples.keys(): for subject in self._triples[p].keys(): for object in self._triples[p][subject]: r.append( Triple((Article(subject), q[1], Article(object))) ) return r else: return [] else: if q[2].type not in var: # ??x for subject in self._striples.keys(): for predicate in self._striples[subject].keys(): if o in self._striples[subject][predicate]: r.append( Triple((Article(subject), Article(predicate), q[2])) ) return r else: return [] else: return list(self) def remove(self, t, loose=1): q = self.query(t, loose) return TripleStore(filter(lambda x: (x not in q), self)) class Store(dict): def __init__(self): self[None] = TripleStore() def __len__(self): result = 0 for formula in self.formulae(): result += len(self[formula]) return result def formulae(self): return self.keys() def append(self, t, formula): assert isinstance(t, Triple) if `formula` in self.formulae(): self[`formula`].append(t) elif formula is None: if None in self.formulae(): self[None].append(t) else: self[None] = TripleStore([t]) else: self[`formula`] = TripleStore([t]) if __name__=="__main__": print __doc__