rdf.py 12 KB

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