rdf.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. import sys
  2. from collections import defaultdict
  3. import os
  4. import rdflib
  5. from rdflib.plugins.sparql import prepareQuery
  6. import json
  7. # Work around Python 2 where a 'big integer' automatically becomes a long
  8. if sys.version > '3': # pragma: no cover
  9. integer_types = (int,)
  10. primitive_types = (int, float, str, bool)
  11. else: # pragma: no cover
  12. integer_types = (int, long)
  13. primitive_types = (int, long, float, str, bool, unicode)
  14. complex_primitives = frozenset(["if", "while", "assign", "call", "break", "continue", "return","resolve","access", "constant", "input", "output", "declare", "global"])
  15. def instance_to_string(value):
  16. return value["value"]
  17. def string_to_instance(value):
  18. return {'value': value}
  19. class ModelverseState(object):
  20. def __init__(self, bootfile = None):
  21. self.graph = rdflib.Graph()
  22. self.mv = rdflib.Namespace("http://modelverse.mv/#")
  23. self.graph.bind("MV", self.mv)
  24. self.free_id = -1
  25. self.prepared_queries = {
  26. "read_value": """
  27. SELECT ?value
  28. WHERE {
  29. ?var1 MV:hasValue ?value .
  30. }
  31. """,
  32. "read_outgoing": """
  33. SELECT ?link
  34. WHERE {
  35. ?link MV:hasSource ?var1 .
  36. }
  37. """,
  38. "read_incoming": """
  39. SELECT ?link
  40. WHERE {
  41. ?link MV:hasTarget ?var1 .
  42. }
  43. """,
  44. "read_edge": """
  45. SELECT ?source ?target
  46. WHERE {
  47. ?var1 MV:hasSource ?source ;
  48. MV:hasTarget ?target .
  49. }
  50. """,
  51. "read_dict_keys": """
  52. SELECT ?key
  53. WHERE {
  54. ?main_edge MV:hasSource ?var1 .
  55. ?attr_edge MV:hasSource ?main_edge ;
  56. MV:hasTarget ?key .
  57. }
  58. """,
  59. "read_dict_node": """
  60. SELECT ?value_node
  61. WHERE {
  62. ?main_edge MV:hasSource ?var1 ;
  63. MV:hasTarget ?value_node .
  64. ?attr_edge MV:hasSource ?main_edge ;
  65. MV:hasTarget ?var2 .
  66. }
  67. """,
  68. "read_dict_node_edge": """
  69. SELECT ?main_edge
  70. WHERE {
  71. ?main_edge MV:hasSource ?var1 .
  72. ?attr_edge MV:hasSource ?main_edge ;
  73. MV:hasTarget ?var2 .
  74. }
  75. """,
  76. "delete_node": """
  77. SELECT ?edge
  78. WHERE {
  79. { ?edge MV:hasTarget ?var1 . }
  80. UNION
  81. { ?edge MV:hasSource ?var1 . }
  82. }
  83. """,
  84. "delete_edge": """
  85. SELECT ?edge
  86. WHERE {
  87. { ?edge MV:hasTarget ?var1 . }
  88. UNION
  89. { ?edge MV:hasSource ?var1 . }
  90. }
  91. """,
  92. }
  93. for k, v in self.prepared_queries.iteritems():
  94. self.prepared_queries[k] = prepareQuery(self.prepared_queries[k], initNs={"MV": self.mv})
  95. self.root = self.parse(bootfile)
  96. def parse(self, filename):
  97. symbols = {}
  98. def resolve(symb):
  99. try:
  100. return int(symb)
  101. except:
  102. if symb[0] == "?":
  103. derefs = symb[1:].split("/")
  104. v, _ = self.read_dict(symbols["root"], "__hierarchy")
  105. for deref in derefs:
  106. v, _ = self.read_dict(v, deref)
  107. return v
  108. else:
  109. return symbols[symb]
  110. with open(filename, 'r') as f:
  111. for line in f:
  112. element_type, constructor = line.split(None, 1)
  113. name, values = constructor.split("(", 1)
  114. name = name.split()[0]
  115. values, _ = values.rsplit(")", 1)
  116. if element_type == "Node":
  117. if values == "":
  118. symbols[name] = self.create_node()
  119. else:
  120. value = values
  121. if value in complex_primitives:
  122. value = string_to_instance(value)
  123. else:
  124. value = eval(value)
  125. symbols[name] = self.create_nodevalue(value)
  126. elif element_type == "Edge":
  127. values = [v.split()[0] for v in values.split(",")]
  128. symbols[name] = self.create_edge(resolve(values[0]), resolve(values[1]))
  129. else:
  130. raise Exception("Unknown element type: %s" % element_type)
  131. return symbols["root"]
  132. def read_root(self):
  133. return self.root
  134. def create_node(self):
  135. self.free_id += 1
  136. return rdflib.URIRef("http://modelverse.mv/#%s" % self.free_id)
  137. def create_edge(self, source, target):
  138. if not isinstance(source, rdflib.URIRef):
  139. return None
  140. elif not isinstance(target, rdflib.URIRef):
  141. return None
  142. self.free_id += 1
  143. edge = rdflib.URIRef("http://modelverse.mv/#%s" % self.free_id)
  144. self.graph.add((edge, self.mv.hasSource, source))
  145. self.graph.add((edge, self.mv.hasTarget, target))
  146. return edge
  147. def is_valid_datavalue(self, value):
  148. if isinstance(value, dict):
  149. if "value" in value and value["value"] in complex_primitives:
  150. return True
  151. else:
  152. return False
  153. elif not isinstance(value, primitive_types):
  154. return False
  155. elif isinstance(value, integer_types) and not (-2**63 <= value <= 2**64 - 1):
  156. return False
  157. return True
  158. def create_nodevalue(self, value):
  159. if not self.is_valid_datavalue(value):
  160. return None
  161. self.free_id += 1
  162. node = rdflib.URIRef("http://modelverse.mv/#%s" % self.free_id)
  163. self.graph.add((node, self.mv.hasValue, rdflib.Literal(json.dumps(value))))
  164. return node
  165. def create_dict(self, source, data, destination):
  166. if not isinstance(source, rdflib.URIRef):
  167. return None
  168. if not isinstance(destination, rdflib.URIRef):
  169. return None
  170. if not self.is_valid_datavalue(data):
  171. return None
  172. n = self.create_nodevalue(data)[0]
  173. e = self.create_edge(source, destination)[0]
  174. self.create_edge(e, n)
  175. return None
  176. def read_value(self, node):
  177. if not isinstance(node, rdflib.URIRef):
  178. return None
  179. result = self.graph.query(self.prepared_queries["read_value"], initBindings={"var1": node})
  180. if len(result) == 0:
  181. return None
  182. return json.loads(list(result)[0][0])
  183. def read_outgoing(self, elem):
  184. if not isinstance(elem, rdflib.URIRef):
  185. return None
  186. result = self.graph.query(self.prepared_queries["read_outgoing"], initBindings={"var1": elem})
  187. return [i[0] for i in result]
  188. def read_incoming(self, elem):
  189. if not isinstance(elem, rdflib.URIRef):
  190. return None
  191. result = self.graph.query(self.prepared_queries["read_incoming"], initBindings={"var1": elem})
  192. return [i[0] for i in result]
  193. def read_edge(self, edge):
  194. result = self.graph.query(self.prepared_queries["read_edge"], initBindings={"var1": edge})
  195. if len(result) == 0:
  196. return [None, None]
  197. else:
  198. return [list(result)[0][0], list(result)[0][1]]
  199. def read_dict(self, node, value):
  200. if not isinstance(node, rdflib.URIRef):
  201. return None
  202. if not self.is_valid_datavalue(value):
  203. return None
  204. q = """
  205. SELECT ?value_node
  206. WHERE {
  207. ?main_edge MV:hasSource <%s> ;
  208. MV:hasTarget ?value_node .
  209. ?attr_edge MV:hasSource ?main_edge ;
  210. MV:hasTarget ?attr_node .
  211. ?attr_node MV:hasValue '%s' .
  212. }
  213. """ % (node, json.dumps(value))
  214. result = self.graph.query(q)
  215. if len(result) == 0:
  216. return None
  217. if len(result) != 1:
  218. raise Exception("Error!")
  219. return list(result)[0][0]
  220. def read_dict_keys(self, node):
  221. if not isinstance(node, rdflib.URIRef):
  222. return None
  223. result = self.graph.query(self.prepared_queries["read_dict_keys"], initBindings={"var1": node})
  224. return [i[0] for i in result]
  225. def read_dict_edge(self, node, value):
  226. if not isinstance(node, rdflib.URIRef):
  227. return None
  228. if not self.is_valid_datavalue(value):
  229. return None
  230. result = self.graph.query(
  231. """
  232. SELECT ?main_edge
  233. WHERE {
  234. ?main_edge MV:hasSource <%s> ;
  235. MV:hasTarget ?value_node .
  236. ?attr_edge MV:hasSource ?main_edge ;
  237. MV:hasTarget ?attr_node .
  238. ?attr_node MV:hasValue '%s' .
  239. }
  240. """ % (node, json.dumps(value)))
  241. if len(result) == 0:
  242. return None
  243. return list(result)[0][0]
  244. def read_dict_node(self, node, value_node):
  245. if not isinstance(node, rdflib.URIRef):
  246. return None
  247. result = self.graph.query(self.prepared_queries["read_dict_node"], initBindings={"var1": node, "var2": value_node})
  248. if len(result) == 0:
  249. return None
  250. return list(result)[0][0]
  251. def read_dict_node_edge(self, node, value_node):
  252. if not isinstance(node, rdflib.URIRef):
  253. return None
  254. result = self.graph.query(self.prepared_queries["read_dict_node_edge"], initBindings={"var1": node, "var2": value_node})
  255. if len(result) == 0:
  256. return None
  257. return list(result)[0][0]
  258. def read_reverse_dict(self, node, value):
  259. if not isinstance(node, rdflib.URIRef):
  260. return None
  261. if not self.is_valid_datavalue(value):
  262. return None
  263. result = self.graph.query(
  264. """
  265. SELECT ?source_node
  266. WHERE {
  267. ?main_edge MV:hasTarget <%s> ;
  268. MV:hasSource ?source_node .
  269. ?attr_edge MV:hasSource ?main_edge ;
  270. MV:hasTarget ?value_node .
  271. ?value_node MV:hasValue '%s' .
  272. }
  273. """ % (node, json.dumps(value)))
  274. return [i[0] for i in result]
  275. def delete_node(self, node):
  276. if node == self.root:
  277. return None
  278. if not isinstance(node, rdflib.URIRef):
  279. return None
  280. # Remove its value if it exists
  281. self.graph.remove((node, None, None))
  282. # Get all edges connecting this
  283. result = self.graph.query(self.prepared_queries["delete_node"], initBindings={"var1": node})
  284. # ... and remove them
  285. print("Got related nodes: " + str(len(result)))
  286. for e in result:
  287. self.delete_edge(e[0])
  288. return None
  289. def delete_edge(self, edge):
  290. if not isinstance(edge, rdflib.URIRef):
  291. return None
  292. # Remove its links
  293. self.graph.remove((edge, None, None))
  294. # Get all edges connecting this
  295. result = self.graph.query(self.prepared_queries["delete_edge"], initBindings={"var1": edge})
  296. # ... and remove them
  297. for e in result:
  298. self.delete_edge(e[0])
  299. return None
  300. def garbage_collect(self):
  301. pass
  302. def purge(self):
  303. pass