#!/usr/bin/python """Eep RDF API: Built-Ins""" __author__ = 'Sean B. Palmer' __license__ = 'Copyright (C) 2001 Sean B. Palmer. GNU GPL 2' import eep, query, infer import copy nslist, builtins = [], {} # Register the namespaces def regns(ns): if ns not in nslist: nslist.append(ns) LOG_NS = 'http://www.w3.org/2000/10/swap/log#' STRING_NS = 'http://www.w3.org/2000/10/swap/string#' UTIL_NS = 'http://example.org/#' regns(LOG_NS) regns(STRING_NS) regns(UTIL_NS) # Create the builtins class BI_log_equalTo: def evaluate(self, t): return (t[0].repr == t[2].repr) class BI_log_notEqualTo: def evaluate(self, t): return (t[0].repr != t[2].repr) class BI_log_uri: def evaluateObject(self, t): if t[0].type == 'URI': t = t[:] return [t[0], t[1], eep.Article('"'+t[0].val+'"')] else: return 1 class BI_log_racine: def evaluateObject(self, t): if t[0].type == 'URI': t = t[:] if '#' in t[0].val: t[2] = eep.Article('<'+t[0][0:(t[0].val.find('#'))]+'>') return [t[0], t[1], t[2]] else: return 1 class BI_log_content: def evaluateObject(self, t): import urllib2 if t[0].type == 'URI': t = t[:] try: content = urllib2.urlopen(t[0].val).read() except: content = 'Error getting URI' return [t[0], t[1], eep.Article('"'+content+'"')] else: return 1 class BI_string_notEqualTo: def evaluate(self, t): if (t[0].type != 'Literal') or (t[2].type != 'Literal'): return 0 else: return (t[0].val != t[2].val) class BI_string_startsWith: def evaluate(self, t): if (t[0].type != 'Literal') or (t[2].type != 'Literal'): return 0 elif (t[0].val[:len(t[2].val)] == t[2].val): return 1 else: return 0 class BI_util_sha512: def evaluateObject(self, t): import sha512 if t[0].type == 'Literal': t = t[:] try: x = sha512.new(t[0].val).hexdigest() except: x = 'Built in failed gently: SHA module problem' return [t[0], t[1], eep.Article('"%s"' % x)] else: return 1 class BI_util_rawType: def evaluateObject(self, t): t = t[:] t2 = eep.Article('"'+t[0].type+'"') return [t[0], t[1], t2] # Register the builtins def register(c, ns, name): builtins[ns+name] = c register(BI_log_equalTo, LOG_NS, 'equalTo') register(BI_log_notEqualTo, LOG_NS, 'notEqualTo') register(BI_log_uri, LOG_NS, 'uri') register(BI_log_racine, LOG_NS, 'racine') register(BI_log_content, LOG_NS, 'content') register(BI_string_notEqualTo, STRING_NS, 'notEqualTo') register(BI_string_startsWith, STRING_NS, 'startsWith') register(BI_util_sha512, UTIL_NS, 'sha512') register(BI_util_rawType, UTIL_NS, 'rawType') # Other stuff def isBI(t): """Tests for a triple using a built-in predicate. This is optimized so that it shouldn't slow down queries too much.""" if t[1].type != 'URI': return 0 do = 0 for ns in nslist: if t[1].val[:len(ns)] == ns: do = 1 if not do: return 0 if t[1].val not in builtins.keys(): return 0 return 1 def bi(t): if (t[0].type == 'Univar') and (t[2].type == 'Univar'): return t elif (t[0].type == 'Univar') and (t[2].type != 'Univar'): return builtins[t[1].val]().evaluateSubject(t) elif (t[0].type != 'Univar') and (t[2].type == 'Univar'): return builtins[t[1].val]().evaluateObject(t) elif (t[0].type != 'Univar') and (t[2].type != 'Univar'): if builtins[t[1].val]().evaluate(t): return 1 else: return 0 def doBuiltIns(queue, bdict, resultDict): """ newbins is a list of built-ins that were taken out before the query. bdict is a list of variables that need to be satisfied in the builtins, and res is the query result. We need to iteratively match the builtins until no more variables are added. Sometimes, we will try to satisfy the variables in a builtin which can only take one thingy. That needs to be resolved. """ TYPE, VAL, subj, pred, obj = 0, 1, 0, 1, 2 DEBUG = 0 # If the query didn't find all of the material needed, then the query fails if None in resultDict.values(): raise "Query not fully satisfied" # For each value in the result dict, add it to the bdict. All values in the # bdict need to be satisfied for the builtins to have passed, and the # builtins need to have passed, of course. for var in resultDict.keys(): # var is a Univar.repr if var in bdict.keys(): bdict[var] = resultDict[var] if DEBUG: print 'res[0]:::', res[0] if DEBUG: print 'resultDict:::', resultDict if DEBUG: print 'bdict:::', bdict # Bung in the initial variables from the resultDict for item in queue: # item is a built-in triple to do for pos in (0, 1, 2): if ((item[pos].type == 'Univar') and (item[pos].repr in resultDict.keys())): bdict[item[pos].repr] = eep.Article(resultDict[item[pos].repr]) item[pos] = eep.Article(resultDict[item[pos].repr]) if DEBUG: print 'queue:::', queue # Now we put the BI types in each member of the queue for i in range(len(queue)): done = 0 for funcname in dir(builtins[queue[i][pred].val]()): if funcname[:8] == 'evaluate': queue[i], done = [funcname, queue[i]], 1 if not done: raise "No evaluate in "+builtins[queue[i][pred].val] if DEBUG: print 'queue:::', queue # Now we need to keep doing builtins for each thing in the queue. We only # stop when * the queue has had all of its BIs done * the queue has not # had any updates in the last iteration # By update, we mean that there are no variables left to satisfy, or truths # to check done = [] # list of builtins that we've done # The following block tests for the type of builtin, and if everything # matches, performs the builtin while 1: qlen, dlen = len(queue), len(done) for biToDo in queue: # subst in any new values for pos in (0, 1, 2): if ((biToDo[VAL][pos].type == 'Univar') and bdict[biToDo[VAL][pos].repr]): biToDo[VAL][pos] = eep.Article(bdict[biToDo[VAL][pos].repr]) if DEBUG: print biToDo[TYPE], biToDo[VAL][subj].type, biToDo[VAL][obj].type if ((biToDo[TYPE] == 'evaluate') and (biToDo[VAL][subj].type != 'Univar') and (biToDo[VAL][obj].type != 'Univar')): biResult = bi(biToDo[VAL]) elif ((biToDo[TYPE] == 'evaluateSubject') and (biToDo[VAL][subj].type == 'Univar') and (biToDo[VAL][obj].type != 'Univar')): biResult = bi(biToDo[VAL]) elif ((biToDo[TYPE] == 'evaluateObject') and (biToDo[VAL][subj].type != 'Univar') and (biToDo[VAL][obj].type == 'Univar')): biResult = bi(biToDo[VAL]) else: biResult = 'not yet' if DEBUG: print 'biResult:::', biResult if biResult == 0: # builtin failed. Go home if DEBUG: print 'Removing because false: '+str(biToDo) queue.remove(biToDo) done.append(0) elif biResult not in (1, 'not yet'): # A list. May have vars, which we need to sub. for pos in (0, 1, 2): if biToDo[VAL][pos].type == 'Univar': bdict[biToDo[VAL][pos].repr] = biResult[pos] biToDo[VAL][pos] = biResult[pos] queue.remove(biToDo) done.append(biToDo[VAL]) elif biResult != 'not yet': # i.e. it equals 1 if DEBUG: print 'Removing because true: '+str(biToDo) queue.remove(biToDo) # we did it. No new vars else: pass if DEBUG: print 'biToDo - done:::', biToDo[VAL] # we've done it once for all items in the queue if (len(queue) == 0) or (not len(done) > dlen): break if DEBUG: print 'done!:::', queue, done if (len(queue) > 0) or (0 in done): # still stuff on the queue? bork! return bdict, [0] else: return bdict, done def bfilter(r, store): desc = r[1] ante = filter(lambda t: not isBI(t), r[0]) bins = filter(lambda t: isBI(t), r[0]) # Make a dictionary of the vars in the builtins bd = {} for triple in bins: for pos in (0, 1, 2): if triple[pos].type[-3:] == 'var': bd[triple[pos].repr] = None qres, result = query.xtquery(ante, store), [] for res in qres: newbins, bdict = [triple[:] for triple in bins], copy.copy(bd) bdict, int = doBuiltIns(newbins, bdict, res[1]) # @@ if len(int) > 0: if int[0] == 0: int = [0] else: int = [] for t in desc: t = t[:] for p in (0, 1, 2): if (t[p].type == 'Univar') and (t[p].repr in res[1].keys()): t[p] = eep.Article(res[1][t[p].repr]) elif (t[p].type == 'Univar') and (t[p].repr in bdict.keys()): t[p] = eep.Article(bdict[t[p].repr]) int.append(t) if len(int) > 0: if int[0] != 0: result.append(int) else: result.append(int) return result if __name__=="__main__": print __doc__