rdf.py 12 KB

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