home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / python-support / python-rdflib / rdflib / sparql / sparqlOperators.py < prev    next >
Encoding:
Python Source  |  2007-04-04  |  13.5 KB  |  464 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. #
  4. # $Date: 2005/11/04 14:06:36 $, by $Author: ivan $, $Revision: 1.1 $
  5. #
  6. ##
  7. # API for the SPARQL operators. The operators (eg, 'lt')
  8. # return a <em>function</em> that can be added to the AND clause of a query. The parameters are either regular values
  9. # or query strings. The resulting function has one parameter (the binding directory), it can be combined with others or
  10. # be plugged to into an array of constraints. For example:
  11. # <pre>
  12. #   constraints = [lt("?m",42)]
  13. #</pre>
  14. # <p>for checking whether "?m" is smaller than the (integer) value 42. It can be combined using the lambda function, for
  15. # example:</p>
  16. # <pre>
  17. #    constraints = [lambda(b) : lt("?m",42")(b) or lt("?n",134)(b)]
  18. # </pre>
  19. # <p>is the expression for:</p>
  20. # <pre>
  21. #    AND ?m < 42 || ?n < 134
  22. # </pre>
  23. # <p>(Clearly, the relative complexity is only on the API level; a SPARQL language parser that starts with a SPARQL
  24. # expression can map on this API).</p>
  25. #
  26. ##
  27.  
  28. import sys, os, re
  29.  
  30. from rdflib.Literal     import Literal
  31. from rdflib.BNode       import BNode
  32. from rdflib.URIRef      import URIRef
  33.  
  34. from rdflib.sparql.graphPattern import _createResource
  35. from rdflib.sparql import _questChar, Debug
  36. from rdflib.sparql.Unbound import Unbound
  37.  
  38. ##
  39. # Boolean test whether this is a a query string or not
  40. # @param v the value to be checked
  41. # @return True if it is a query string
  42. def queryString(v) :
  43.     return isinstance(v,basestring) and len(v) != 0 and v[0] == _questChar
  44.  
  45. ##
  46. # Return the value in a literal, making on the fly conversion on datatype (using the datatypes that are implemented)
  47. # @param v the Literal to be converted
  48. # @return the result of the conversion.
  49. def getLiteralValue(v) :
  50.     return v
  51.  
  52. ##
  53. # Returns a <em>value retrieval function</em>. The return value can be plugged in a query; it would return
  54. # the value of param directly if param is a real value, and the run-time value if param is a query string of the type
  55. # "?xxx". If no binding is defined at the time of call, the return value is None
  56. # @param param query string, Unbound instance, or real value
  57. # @return a function taking one parameter (the binding directory)
  58. def getValue(param) :
  59.     if isinstance(param,Unbound) :
  60.         param = param.name
  61.         unBound = True
  62.     else :
  63.         unBound = queryString(param)
  64.         if not unBound :
  65.             if isinstance(param,Literal) :
  66.                 value = getLiteralValue(param)
  67.             elif callable(param):
  68.                 return param
  69.             else :
  70.                 value = param
  71.             return lambda(bindings): value
  72.     def f(bindings) :
  73.         if unBound :
  74.             val = bindings[param]
  75.             if isinstance(val,Literal) :
  76.                 return getLiteralValue(val)
  77.             else :
  78.                 return val
  79.         else :
  80.             return value
  81.     return f
  82.  
  83. ##
  84. # Operator for '<'
  85. # @param a value or query string
  86. # @param b value or query string
  87. # @return comparison method
  88. def lt(a,b) :
  89.     fa = getValue(a)
  90.     fb = getValue(b)
  91.     def f(bindings) :
  92.         try :
  93.             return fa(bindings) < fb(bindings)
  94.         except:
  95.             # this is the case when the operators are incompatible
  96.             if Debug :
  97.                 (typ,val,traceback) = sys.exc_info()
  98.                 sys.excepthook(typ,val,traceback)
  99.             return False
  100.     return f
  101.  
  102. ##
  103. # Operator for '<='
  104. # @param a value or query string
  105. # @param b value or query string
  106. # @return comparison method
  107. def le(a,b) :
  108.     fa = getValue(a)
  109.     fb = getValue(b)
  110.     def f(bindings) :
  111.         try :
  112.             return fa(bindings) <= fb(bindings)
  113.         except :
  114.             # this is the case when the operators are incompatible
  115.             if Debug :
  116.                 (typ,val,traceback) = sys.exc_info()
  117.                 sys.excepthook(typ,val,traceback)
  118.             return False
  119.     return f
  120.  
  121. ##
  122. # Operator for '>'
  123. # @param a value or query string
  124. # @param b value or query string
  125. # @return comparison method
  126. def gt(a,b) :
  127.     fa = getValue(a)
  128.     fb = getValue(b)
  129.     def f(bindings) :
  130.         try :
  131.             return fa(bindings) > fb(bindings)
  132.         except :
  133.             # this is the case when the operators are incompatible
  134.             if Debug :
  135.                 (typ,val,traceback) = sys.exc_info()
  136.                 sys.excepthook(typ,val,traceback)
  137.             return False
  138.     return f
  139.  
  140. ##
  141. # Operator for '>='
  142. # @param a value or query string
  143. # @param b value or query string
  144. # @return comparison method
  145. def ge(a,b) :
  146.     fa = getValue(a)
  147.     fb = getValue(b)
  148.     def f(bindings) :
  149.         try :
  150.             return fa(bindings) >= fb(bindings)
  151.         except :
  152.             # this is the case when the operators are incompatible
  153.             if Debug :
  154.                 (typ,val,traceback) = sys.exc_info()
  155.                 sys.excepthook(typ,val,traceback)
  156.             return False
  157.     return f
  158.  
  159. ##
  160. # Operator for '='
  161. # @param a value or query string
  162. # @param b value or query string
  163. # @return comparison method
  164. def eq(a,b) :
  165.     fa = getValue(a)
  166.     fb = getValue(b)
  167.     def f(bindings) :
  168.         try :
  169.             return fa(bindings) == fb(bindings)
  170.         except :
  171.             # this is the case when the operators are incompatible
  172.             if Debug :
  173.                 (typ,val,traceback) = sys.exc_info()
  174.                 sys.excepthook(typ,val,traceback)
  175.             return False
  176.     return f
  177. ##
  178. # Operator for '!='
  179. # @param a value or query string
  180. # @param b value or query string
  181. # @return comparison method
  182. def neq(a,b) :
  183.     fa = getValue(a)
  184.     fb = getValue(b)
  185.     def f(bindings) :
  186.         try :
  187.             return fa(bindings) != fb(bindings)
  188.         except :
  189.             # this is the case when the operators are incompatible
  190.             if Debug :
  191.                 (typ,val,traceback) = sys.exc_info()
  192.                 sys.excepthook(typ,val,traceback)
  193.             return False
  194.     return f
  195.  
  196. def __getQueryString(v) :
  197.     if isinstance(v,Unbound) :
  198.         return v.name
  199.     elif queryString(v) :
  200.         return v
  201.     else :
  202.         return None
  203.  
  204.  
  205. ##
  206. # Is the variable bound
  207. # @param a value or query string
  208. # @return check method
  209. def bound(a) :
  210.     v = __getQueryString(a)
  211.     def f(bindings) :
  212.         if v == None :
  213.             return False
  214.         if v in bindings :
  215.             val = bindings[v]
  216.             return not (val == None)
  217.         else :
  218.             return False
  219.     return f
  220.  
  221. ##
  222. # Is the variable bound to a URIRef
  223. # @param a value or query string
  224. # @return check method
  225. def isURI(a) :
  226.     v = __getQueryString(a)
  227.     def f(bindings) :
  228.         if v == None :
  229.             return False
  230.         try :
  231.             val = bindings[v]
  232.             if val == None:
  233.                 return False
  234.             else :
  235.                 return isinstance(val,URIRef)
  236.         except :
  237.             return False
  238.     return f
  239.  
  240. ##
  241. # Is the variable bound to a IRIRef (this is just an alias for URIRef)
  242. # @param a value or query string
  243. # @return check method
  244. def isIRI(a) :
  245.     return isURI(a)
  246.  
  247. ##
  248. # Is the variable bound to a Blank Node
  249. # @param a value or query string
  250. # @return check method
  251. def isBlank(a) :
  252.     v = __getQueryString(a)
  253.     def f(bindings) :
  254.         if v == None :
  255.             return False
  256.         try :
  257.             val = bindings[v]
  258.             if val == None:
  259.                 return False
  260.             else :
  261.                 return isinstance(val,BNode)
  262.         except :
  263.             return False
  264.     return f
  265.  
  266. ##
  267. # Is the variable bound to a Literal
  268. # @param a value or query string
  269. # @return check method
  270. def isLiteral(a) :
  271.     v = __getQueryString(a)
  272.     def f(bindings) :
  273.         if v == None :
  274.             return False
  275.         try :
  276.             val = bindings[v]
  277.             if val == None:
  278.                 return False
  279.             else :
  280.                 return isinstance(val,Literal)
  281.         except :
  282.             return False
  283.     return f
  284.  
  285. ##
  286. # Return the string version of a resource
  287. # @param a value or query string
  288. # @return check method
  289. def str(a) :
  290.     v = __getQueryString(a)
  291.     def f(bindings) :
  292.         if v == None :
  293.             return ""
  294.         try :
  295.             val = bindings[v]
  296.             if val == None:
  297.                 return ""
  298.             else :
  299.                 return `val`
  300.         except :
  301.             return ""
  302.     return f
  303.  
  304. ##
  305. # Return the lang value of a literal
  306. # @param a value or query string
  307. # @return check method
  308. def lang(a) :
  309.     v = __getQueryString(a)
  310.     def f(bindings) :
  311.         if v == None: return ""
  312.         try :
  313.             val = bindings[v]
  314.             if val == None:
  315.                 return ""
  316.             else :
  317.                 return val.lang
  318.         except :
  319.             return ""
  320.     return f
  321.  
  322. ##
  323. # Return the datatype URI of a literal
  324. # @param a value or query string
  325. # @return check method
  326. def datatype(a) :
  327.     v = __getQueryString(a)
  328.     def f(bindings) :
  329.         if v == None:
  330.             if isinstance(a,Literal):
  331.                 return a.datatype
  332.             else:
  333.                 return ""
  334.  
  335.         try :
  336.             val = bindings[v]
  337.             if val == None:
  338.                 return ""
  339.             else :
  340.                 return val.datatype
  341.         except :
  342.             return ""
  343.     return f
  344.  
  345.  
  346. ##
  347. # Is a resource on a collection. The operator can be used to check whether
  348. #    the 'item' is an element of the 'collection' (a.k.a. list). Both collection and item can
  349. #    be a real resource or a query string.
  350. # @param collection is either a query string (that has to be bound by the query) or an RDFLib Resource
  351. # representing the collection
  352. # @param item is either a query string (that has to be bound by the query), an RDFLib Resource, or
  353. # a data type value that is turned into a corresponding Literal (with possible datatype)
  354. # that must be tested to be part of the collection
  355. # @defreturn a function
  356. def isOnCollection(collection,item, triplets) :
  357.     """Generate a method that can be used as a global constaint in sparql to check whether
  358.     the 'item' is an element of the 'collection' (a.k.a. list). Both collection and item can
  359.     be a real resource or a query string. Furthermore, item might be a plain string, that is
  360.     then turned into a literal run-time.
  361.     The method returns an adapted method.
  362.     """
  363.     #check_subject(collection)
  364.     collUnbound = False
  365.     if isinstance(collection,Unbound) :
  366.         collUnbound = True
  367.         collection  = collection.name
  368.     elif queryString(collection) :
  369.         # just keep 'collection', no reason to reassign
  370.         collUnbound = True
  371.     else:
  372.         collUnbound = False
  373.         # if we got here, this is a valid collection resource
  374.     if isinstance(item,Unbound) :
  375.         queryItem = item.name
  376.         itUnbund  = True
  377.     elif queryString(item) :
  378.         queryItem = item
  379.         itUnbound = True
  380.     else :
  381.         # Note that an exception is raised if the 'item' is invalid
  382.         queryItem = _createResource(item)
  383.         itUnbound = False
  384.     def checkCollection(bindings) :
  385.         try :
  386.             if collUnbound == True :
  387.                 # the binding should come from the binding
  388.                 coll = bindings[collection]
  389.             else :
  390.                 coll = collection
  391.             if itUnbound == True :
  392.                 it = bindings[queryItem]
  393.             else :
  394.                 it = queryItem
  395.             return it in triplets.items(coll)
  396.         except :
  397.             # this means that the binding is not available. But that also means that
  398.             # the global constraint was used, for example, with the optional triplets;
  399.             # not available binding means that the method is irrelevant for those
  400.             # ie, it should not become a show-stopper, hence it returns True
  401.             return True
  402.     return checkCollection
  403.  
  404.  
  405. def addOperator(args,combinationArg):
  406.     """
  407.     SPARQL numeric + operator implemented via Python
  408.     """
  409.     return ' + '.join(["sparqlOperators.getValue(%s)%s"%(i,combinationArg and "(%s)"%combinationArg or '') for i in args])
  410.  
  411. def XSDCast(source,target=None):
  412.     """
  413.     XSD Casting/Construction Support
  414.     For now (this may be an issue since Literal doesn't override comparisons) it simply creates
  415.     a Literal with the target datatype using the 'lexical' value of the source
  416.     """
  417.     sFunc = getValue(source)
  418.     def f(bindings):
  419.         rt = sFunc(bindings)
  420.         if isinstance(rt,Literal) and rt.datatype == target:
  421.             #Literal already has target datatype
  422.             return rt
  423.         else:
  424.             return Literal(rt,datatype=target)
  425.     return f
  426.  
  427. def regex(item,pattern,flag=None):
  428.     """
  429.     Invokes the XPath fn:matches function to match text against a regular expression pattern.
  430.     The regular expression language is defined in XQuery 1.0 and XPath 2.0 Functions and Operators section 7.6.1 Regular Expression Syntax
  431.     """
  432.     a = getValue(item)
  433.     b = getValue(pattern)
  434.     if flag:
  435.         cFlag = 0
  436.         usedFlags = []
  437.         #Maps XPath REGEX flags (http://www.w3.org/TR/xpath-functions/#flags) to Python's re flags
  438.         for fChar,_flag in [('i',re.IGNORECASE),('s',re.DOTALL),('m',re.MULTILINE)]:
  439.             if fChar in flag and fChar not in usedFlags:
  440.                 cFlag |= _flag
  441.                 usedFlags.append(fChar)
  442.         def f1(bindings):
  443.             try:
  444.                 return bool(re.compile(b(bindings),cFlag).search(a(bindings)))
  445.             except:
  446.                 return False
  447.         return f1
  448.     else:
  449.         def f2(bindings):
  450.             try:
  451.                 return bool(re.compile(b(bindings)).search(a(bindings)))
  452.             except:
  453.                 return False
  454.         return f2
  455.  
  456.     def f(bindings):
  457.         try:
  458.             print "%s %s"%(a(bindings),b(bindings))
  459.             return bool(re.compile(a(bindings)).search(b(bindings)))
  460.         except Exception,e:
  461.             print e
  462.             return False
  463.     return f
  464.