123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- from modelverse_state import status
- import sys
- from collections import defaultdict
- import os
- import rdflib
- from rdflib.plugins.sparql import prepareQuery
- import json
- # Work around Python 2 where a 'big integer' automatically becomes a long
- if sys.version > '3': # pragma: no cover
- integer_types = (int,)
- primitive_types = (int, float, str, bool)
- else: # pragma: no cover
- integer_types = (int, long)
- primitive_types = (int, long, float, str, bool, unicode)
- complex_primitives = frozenset(["if", "while", "assign", "call", "break", "continue", "return","resolve","access", "constant", "input", "output", "declare", "global"])
- def instance_to_string(value):
- return value["value"]
- def string_to_instance(value):
- return {'value': value}
- class ModelverseState(object):
- def __init__(self, bootfile = None):
- self.graph = rdflib.Graph()
- self.mv = rdflib.Namespace("http://modelverse.mv/#")
- self.graph.bind("MV", self.mv)
- self.free_id = -1
- self.prepared_queries = {
- "read_value": """
- SELECT ?value
- WHERE {
- ?var1 MV:hasValue ?value .
- }
- """,
- "read_outgoing": """
- SELECT ?link
- WHERE {
- ?link MV:hasSource ?var1 .
- }
- """,
- "read_incoming": """
- SELECT ?link
- WHERE {
- ?link MV:hasTarget ?var1 .
- }
- """,
- "read_edge": """
- SELECT ?source ?target
- WHERE {
- ?var1 MV:hasSource ?source ;
- MV:hasTarget ?target .
- }
- """,
- "read_dict_keys": """
- SELECT ?key
- WHERE {
- ?main_edge MV:hasSource ?var1 .
- ?attr_edge MV:hasSource ?main_edge ;
- MV:hasTarget ?key .
- }
- """,
- "read_dict_node": """
- SELECT ?value_node
- WHERE {
- ?main_edge MV:hasSource ?var1 ;
- MV:hasTarget ?value_node .
- ?attr_edge MV:hasSource ?main_edge ;
- MV:hasTarget ?var2 .
- }
- """,
- "read_dict_node_edge": """
- SELECT ?main_edge
- WHERE {
- ?main_edge MV:hasSource ?var1 .
- ?attr_edge MV:hasSource ?main_edge ;
- MV:hasTarget ?var2 .
- }
- """,
- "delete_node": """
- SELECT ?edge
- WHERE {
- { ?edge MV:hasTarget ?var1 . }
- UNION
- { ?edge MV:hasSource ?var1 . }
- }
- """,
- "delete_edge": """
- SELECT ?edge
- WHERE {
- { ?edge MV:hasTarget ?var1 . }
- UNION
- { ?edge MV:hasSource ?var1 . }
- }
- """,
- }
- for k, v in self.prepared_queries.iteritems():
- self.prepared_queries[k] = prepareQuery(self.prepared_queries[k], initNs={"MV": self.mv})
- self.root = self.parse(bootfile)
- def parse(self, filename):
- symbols = {}
- def resolve(symb):
- try:
- return int(symb)
- except:
- if symb[0] == "?":
- derefs = symb[1:].split("/")
- v, _ = self.read_dict(symbols["root"], "__hierarchy")
- for deref in derefs:
- v, _ = self.read_dict(v, deref)
- return v
- else:
- return symbols[symb]
- with open(filename, 'r') as f:
- for line in f:
- element_type, constructor = line.split(None, 1)
- name, values = constructor.split("(", 1)
- name = name.split()[0]
- values, _ = values.rsplit(")", 1)
- if element_type == "Node":
- if values == "":
- symbols[name], status = self.create_node()
- else:
- value = values
- if value in complex_primitives:
- value = string_to_instance(value)
- else:
- value = eval(value)
- symbols[name], status = self.create_nodevalue(value)
- elif element_type == "Edge":
- values = [v.split()[0] for v in values.split(",")]
- symbols[name], status = self.create_edge(resolve(values[0]), resolve(values[1]))
- else:
- raise Exception("Unknown element type: %s" % element_type)
- if status != 100:
- raise Exception("Failed to process line for reason %s: %s" % (status, line))
- return symbols["root"]
- def read_root(self):
- return (self.root, status.SUCCESS)
- def create_node(self):
- self.free_id += 1
- return (rdflib.URIRef("http://modelverse.mv/#%s" % self.free_id), status.SUCCESS)
- def create_edge(self, source, target):
- if not isinstance(source, rdflib.URIRef):
- return (None, status.FAIL_CE_SOURCE)
- if not isinstance(target, rdflib.URIRef):
- return (None, status.FAIL_CE_TARGET)
- self.free_id += 1
- edge = rdflib.URIRef("http://modelverse.mv/#%s" % self.free_id)
- self.graph.add((edge, self.mv.hasSource, source))
- self.graph.add((edge, self.mv.hasTarget, target))
- return (edge, status.SUCCESS)
-
- def is_valid_datavalue(self, value):
- if isinstance(value, dict):
- if "value" in value and value["value"] in complex_primitives:
- return True
- else:
- return False
- elif not isinstance(value, primitive_types):
- return False
- elif isinstance(value, integer_types) and not (-2**63 <= value <= 2**64 - 1):
- return False
- return True
- def create_nodevalue(self, value):
- if not self.is_valid_datavalue(value):
- return (None, status.FAIL_CNV_OOB)
- self.free_id += 1
- node = rdflib.URIRef("http://modelverse.mv/#%s" % self.free_id)
- self.graph.add((node, self.mv.hasValue, rdflib.Literal(json.dumps(value))))
- return (node, status.SUCCESS)
- def create_dict(self, source, data, destination):
- if not isinstance(source, rdflib.URIRef):
- return (None, status.FAIL_CDICT_SOURCE)
- if not isinstance(destination, rdflib.URIRef):
- return (None, status.FAIL_CDICT_TARGET)
- if not self.is_valid_datavalue(data):
- return (None, status.FAIL_CDICT_OOB)
- n = self.create_nodevalue(data)[0]
- e = self.create_edge(source, destination)[0]
- self.create_edge(e, n)
- return (None, status.SUCCESS)
- def read_value(self, node):
- if not isinstance(node, rdflib.URIRef):
- return (None, status.FAIL_RV_UNKNOWN)
- result = self.graph.query(self.prepared_queries["read_value"], initBindings={"var1": node})
- if len(result) == 0:
- return (None, status.FAIL_RV_NO_VALUE)
- return (json.loads(list(result)[0][0]), status.SUCCESS)
- def read_outgoing(self, elem):
- if not isinstance(elem, rdflib.URIRef):
- return (None, status.FAIL_RO_UNKNOWN)
- result = self.graph.query(self.prepared_queries["read_outgoing"], initBindings={"var1": elem})
- return ([i[0] for i in result], status.SUCCESS)
- def read_incoming(self, elem):
- if not isinstance(elem, rdflib.URIRef):
- return (None, status.FAIL_RI_UNKNOWN)
- result = self.graph.query(self.prepared_queries["read_incoming"], initBindings={"var1": elem})
- return ([i[0] for i in result], status.SUCCESS)
- def read_edge(self, edge):
- result = self.graph.query(self.prepared_queries["read_edge"], initBindings={"var1": edge})
- if len(result) == 0:
- return ([None, None], status.FAIL_RE_UNKNOWN)
- else:
- return ([list(result)[0][0], list(result)[0][1]], status.SUCCESS)
- def read_dict(self, node, value):
- if not isinstance(node, rdflib.URIRef):
- return (None, status.FAIL_RDICT_UNKNOWN)
- if not self.is_valid_datavalue(value):
- return (None, status.FAIL_RDICT_OOB)
- q = """
- SELECT ?value_node
- WHERE {
- ?main_edge MV:hasSource <%s> ;
- MV:hasTarget ?value_node .
- ?attr_edge MV:hasSource ?main_edge ;
- MV:hasTarget ?attr_node .
- ?attr_node MV:hasValue '%s' .
- }
- """ % (node, json.dumps(value))
- result = self.graph.query(q)
- if len(result) == 0:
- return (None, status.FAIL_RDICT_NOT_FOUND)
- if len(result) != 1:
- print(value)
- raise Exception("Error!")
- return (list(result)[0][0], status.SUCCESS)
- def read_dict_keys(self, node):
- if not isinstance(node, rdflib.URIRef):
- return (None, status.FAIL_RDICT_UNKNOWN)
- result = self.graph.query(self.prepared_queries["read_dict_keys"], initBindings={"var1": node})
- return ([i[0] for i in result], status.SUCCESS)
- def read_dict_edge(self, node, value):
- if not isinstance(node, rdflib.URIRef):
- return (None, status.FAIL_RDICTE_UNKNOWN)
- if not self.is_valid_datavalue(value):
- return (None, status.FAIL_RDICTE_OOB)
- result = self.graph.query(
- """
- SELECT ?main_edge
- WHERE {
- ?main_edge MV:hasSource <%s> ;
- MV:hasTarget ?value_node .
- ?attr_edge MV:hasSource ?main_edge ;
- MV:hasTarget ?attr_node .
- ?attr_node MV:hasValue '%s' .
- }
- """ % (node, json.dumps(value)))
- if len(result) == 0:
- return (None, status.FAIL_RDICTE_NOT_FOUND)
- return (list(result)[0][0], status.SUCCESS)
- def read_dict_node(self, node, value_node):
- if not isinstance(node, rdflib.URIRef):
- return (None, status.FAIL_RDICTN_UNKNOWN)
- result = self.graph.query(self.prepared_queries["read_dict_node"], initBindings={"var1": node, "var2": value_node})
- if len(result) == 0:
- return (None, status.FAIL_RDICTN_NOT_FOUND)
- return (list(result)[0][0], status.SUCCESS)
- def read_dict_node_edge(self, node, value_node):
- if not isinstance(node, rdflib.URIRef):
- return (None, status.FAIL_RDICTNE_UNKNOWN)
- result = self.graph.query(self.prepared_queries["read_dict_node_edge"], initBindings={"var1": node, "var2": value_node})
- if len(result) == 0:
- return (None, status.FAIL_RDICTNE_NOT_FOUND)
- return (list(result)[0][0], status.SUCCESS)
- def read_reverse_dict(self, node, value):
- if not isinstance(node, rdflib.URIRef):
- return (None, status.FAIL_RRDICT_UNKNOWN)
- if not self.is_valid_datavalue(value):
- return (None, status.FAIL_RRDICT_OOB)
- result = self.graph.query(
- """
- SELECT ?source_node
- WHERE {
- ?main_edge MV:hasTarget <%s> ;
- MV:hasSource ?source_node .
- ?attr_edge MV:hasSource ?main_edge ;
- MV:hasTarget ?value_node .
- ?value_node MV:hasValue '%s' .
- }
- """ % (node, json.dumps(value)))
- return ([i[0] for i in result], status.SUCCESS)
- def delete_node(self, node):
- if node == self.root:
- return (None, status.FAIL_DN_UNKNOWN)
- if not isinstance(node, rdflib.URIRef):
- return (None, status.FAIL_DN_UNKNOWN)
- # Remove its value if it exists
- self.graph.remove((node, None, None))
- # Get all edges connecting this
- result = self.graph.query(self.prepared_queries["delete_node"], initBindings={"var1": node})
- # ... and remove them
- print("Got related nodes: " + str(len(result)))
- for e in result:
- self.delete_edge(e[0])
- return (None, status.SUCCESS)
- def delete_edge(self, edge):
- if not isinstance(edge, rdflib.URIRef):
- return (None, status.FAIL_DN_UNKNOWN)
- # Remove its links
- self.graph.remove((edge, None, None))
- # Get all edges connecting this
- result = self.graph.query(self.prepared_queries["delete_edge"], initBindings={"var1": edge})
- # ... and remove them
- for e in result:
- self.delete_edge(e[0])
- return (None, status.SUCCESS)
- def garbage_collect(self):
- pass
- def purge(self):
- pass
|