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 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.mv = rdflib.Namespace("http://modelverse.mv/#")
  23. self.graph.bind("MV", self.mv)
  24. self.parse(bootfile)
  25. self.root = 0
  26. self.GC = True
  27. self.to_delete = set()
  28. def parse(self, filename):
  29. triplestore = filename + ".n3"
  30. try:
  31. if os.path.getmtime(triplestore) > os.path.getmtime(filename):
  32. self.graph.parse(filename, format="n3")
  33. else:
  34. raise Exception("Invalid triplestore")
  35. except Exception as e:
  36. # We have to parse the file and create the pickle
  37. symbols = {}
  38. def resolve(symb):
  39. try:
  40. return int(symb)
  41. except:
  42. if symb[0] == "?":
  43. derefs = symb[1:].split("/")
  44. v, _ = self.read_dict(symbols["root"], "__hierarchy")
  45. for deref in derefs:
  46. v, _ = self.read_dict(v, deref)
  47. return v
  48. else:
  49. return symbols[symb]
  50. with open(filename, 'r') as f:
  51. for line in f:
  52. element_type, constructor = line.split(None, 1)
  53. name, values = constructor.split("(", 1)
  54. name = name.split()[0]
  55. values, _ = values.rsplit(")", 1)
  56. if element_type == "Node":
  57. if values == "":
  58. symbols[name], status = self.create_node()
  59. else:
  60. value = values
  61. if value in complex_primitives:
  62. value = string_to_instance(value)
  63. else:
  64. value = eval(value)
  65. symbols[name], status = self.create_nodevalue(value)
  66. elif element_type == "Edge":
  67. values = [v.split()[0] for v in values.split(",")]
  68. symbols[name], status = self.create_edge(resolve(values[0]), resolve(values[1]))
  69. else:
  70. raise Exception("Unknown element type: %s" % element_type)
  71. if status != 100:
  72. raise Exception("Failed to process line for reason %s: %s" % (status, line))
  73. # Creation successful, now also create a pickle
  74. self.graph.serialize(triplestore, format="n3")
  75. #TODO this loses information about the root!
  76. return symbols["root"]
  77. def read_root(self):
  78. return (self.root, status.SUCCESS)
  79. def create_node(self):
  80. return (rdflib.BNode(), status.SUCCESS)
  81. def create_edge(self, source, target):
  82. if not isinstance(source, rdflib.BNode):
  83. return (None, status.FAIL_CE_SOURCE)
  84. if not isinstance(target, rdflib.BNode):
  85. return (None, status.FAIL_CE_TARGET)
  86. edge = rdflib.BNode()
  87. self.graph.add((edge, self.mv.hasSource, source))
  88. self.graph.add((edge, self.mv.hasTarget, target))
  89. return (edge, status.SUCCESS)
  90. def is_valid_datavalue(self, value):
  91. if isinstance(value, dict):
  92. if "value" in value and value["value"] in complex_primitives:
  93. return True
  94. else:
  95. return False
  96. elif not isinstance(value, primitive_types):
  97. return False
  98. elif isinstance(value, integer_types) and not (-2**63 <= value <= 2**64 - 1):
  99. return False
  100. return True
  101. def create_nodevalue(self, value):
  102. if not self.is_valid_datavalue(value):
  103. return (None, status.FAIL_CNV_OOB)
  104. node = rdflib.BNode()
  105. self.graph.add((node, self.mv.hasValue, rdflib.Literal(value)))
  106. return (node, status.SUCCESS)
  107. def create_dict(self, source, data, destination):
  108. if not isinstance(source, rdflib.BNode):
  109. return (None, status.FAIL_CDICT_SOURCE)
  110. if not isinstance(target, rdflib.BNode):
  111. return (None, status.FAIL_CDICT_TARGET)
  112. if not self.is_valid_datavalue(data):
  113. return (None, status.FAIL_CDICT_OOB)
  114. n = self.create_nodevalue(data)[0]
  115. e = self.create_edge(source, destination)[0]
  116. self.create_edge(e, n)
  117. return (None, status.SUCCESS)
  118. def read_value(self, node):
  119. if not isinstance(node, rdflib.BNode):
  120. return (None, status.FAIL_RV_UNKNOWN)
  121. result = self.graph.query(
  122. """
  123. SELECT ?value
  124. WHERE {
  125. _:%s MV:hasValue ?value .
  126. }
  127. """ % node)
  128. if len(result) == 0:
  129. return (None, status.FAIL_RV_NO_VALUE)
  130. return (result[0], status.SUCCESS)
  131. def read_outgoing(self, elem):
  132. if not isinstance(elem, rdflib.BNode):
  133. return (None, status.FAIL_RO_UNKNOWN)
  134. result = self.graph.query(
  135. """
  136. SELECT ?link
  137. WHERE {
  138. _:%s "hasTarget" ?link .
  139. }
  140. """ % elem)
  141. return (list(result), status.SUCCESS)
  142. def read_incoming(self, elem):
  143. if not isinstance(elem, rdflib.BNode):
  144. return (None, status.FAIL_RI_UNKNOWN)
  145. result = self.graph.query(
  146. """
  147. SELECT ?link
  148. WHERE {
  149. _:%s MV:hasSource ?link .
  150. }
  151. """ % elem)
  152. return (list(result), status.SUCCESS)
  153. def read_edge(self, edge):
  154. result = self.graph.query(
  155. """
  156. SELECT ?source, ?target
  157. WHERE {
  158. _:%s MV:hasSource ?source ;
  159. MV:hasTarget ?target .
  160. }
  161. """ % edge)
  162. if len(result) == 0:
  163. return ([None, None], status.FAIL_RE_UNKNOWN)
  164. else:
  165. return (list(result), status.SUCCESS)
  166. def read_dict(self, node, value):
  167. if not isinstance(node, rdflib.BNode):
  168. return (None, status.FAIL_RDICT_UNKNWON)
  169. if not self.is_valid_datavalue(value):
  170. return (None, status.FAIL_RDICT_OOB)
  171. q = """
  172. SELECT ?value
  173. WHERE {
  174. ?main_edge MV:hasSource _:%s .
  175. ?main_edge MV:hasTarget ?value_node .
  176. ?attr_edge MV:hasSource ?main_edge ;
  177. MV:hasTarget ?attr_node .
  178. ?attr_node MV:hasValue %s .
  179. ?value_node MV:hasValue ?value .
  180. }
  181. """ % (node, 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 (result[0], status.SUCCESS)
  187. def read_dict_keys(self, node):
  188. if not isinstance(node, rdflib.BNode):
  189. return (None, status.FAIL_RDICT_UNKNWON)
  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