rdf.py 14 KB

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