|
@@ -1,10 +1,12 @@
|
|
|
import urllib
|
|
|
+import urllib2
|
|
|
import json
|
|
|
import random
|
|
|
+from urllib2 import URLError
|
|
|
import sys
|
|
|
import time
|
|
|
import threading
|
|
|
-import uuid
|
|
|
+import Queue
|
|
|
|
|
|
from sccd.runtime.statecharts_core import Event
|
|
|
|
|
@@ -22,8 +24,6 @@ MODE_SERVICE = 6
|
|
|
sys.path.append(COMPILER_PATH)
|
|
|
from hutn_compiler.compiler import main as do_compile
|
|
|
|
|
|
-import socket2event
|
|
|
-
|
|
|
# Exceptions
|
|
|
class ModelverseException(Exception):
|
|
|
pass
|
|
@@ -63,25 +63,20 @@ class UnknownMetamodellingHierarchy(ModelverseException):
|
|
|
|
|
|
# Helper functions and configuration: do not use yourself!
|
|
|
taskname = None
|
|
|
+address = None
|
|
|
mode = MODE_UNCONNECTED
|
|
|
prev_mode = None
|
|
|
current_model = None
|
|
|
registered_metamodels = {}
|
|
|
outputs = [None]
|
|
|
-ctrl_input = None
|
|
|
-ctrl_output = None
|
|
|
|
|
|
def _output_thread(outputs, taskname):
|
|
|
- req_out = ctrl_output.addOutputListener("request_out")
|
|
|
- my_id = str(uuid.uuid4())
|
|
|
+ while taskname is None:
|
|
|
+ time.sleep(0.1)
|
|
|
|
|
|
try:
|
|
|
while 1:
|
|
|
- ctrl_output.addInput(Event("HTTP_input", "request_in", [urllib.urlencode({"op": "get_output", "taskname": taskname}), my_id]))
|
|
|
-
|
|
|
- event = req_out.fetch(-1)
|
|
|
- if event.parameters[1] == my_id:
|
|
|
- outputs.append(json.loads(event.parameters[0]))
|
|
|
+ outputs.append(json.loads(urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "taskname": taskname}))).read()))
|
|
|
except:
|
|
|
pass
|
|
|
|
|
@@ -108,7 +103,7 @@ def _exec_on_statechart(statechart):
|
|
|
# Expand the event and make it HTTP input
|
|
|
_input(input_event.parameters)
|
|
|
|
|
|
- time.sleep(0.02)
|
|
|
+ time.sleep(0.01)
|
|
|
|
|
|
thrd = threading.Thread(target=_exec_sc, args=statechart)
|
|
|
thrd.daemon = True
|
|
@@ -165,19 +160,20 @@ def _goto_mode(new_mode, model_name=None):
|
|
|
|
|
|
def _input(value, port=None):
|
|
|
# Ugly json encoding of primitives
|
|
|
- #print("[IN] %s" % value)
|
|
|
+ print("[IN] %s" % value)
|
|
|
if port is None:
|
|
|
port = taskname
|
|
|
if isinstance(value, type([])):
|
|
|
value = json.dumps(value)
|
|
|
- ctrl_input.addInput(Event("HTTP_input", "request_in", [urllib.urlencode({"op": "set_input", "taskname": port, "data": value}), None]))
|
|
|
+ urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "data": value, "taskname": port}))).read()
|
|
|
else:
|
|
|
value = json.dumps(value)
|
|
|
- ctrl_input.addInput(Event("HTTP_input", "request_in", [urllib.urlencode({"op": "set_input", "taskname": port, "value": value}), None]))
|
|
|
+ #print("Set input: " + str(value))
|
|
|
+ urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "value": value, "taskname": port}))).read()
|
|
|
|
|
|
def _input_raw(value, taskname):
|
|
|
# Ugly json encoding of primitives
|
|
|
- ctrl_input.addInput(Event("HTTP_input", "request_in", [urllib.urlencode({"op": "set_input", "taskname": taskname, "value": value}), None]))
|
|
|
+ urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "value": value, "taskname": taskname}))).read()
|
|
|
|
|
|
def _compile_AL(code):
|
|
|
# Compile an action language file and send the compiled code
|
|
@@ -216,10 +212,11 @@ def _compile_model(code):
|
|
|
def _output(expected=None):
|
|
|
try:
|
|
|
while len(outputs) < 2:
|
|
|
- time.sleep(0.02)
|
|
|
+ time.sleep(0.5)
|
|
|
+ print("Sleep for output: " + str(outputs))
|
|
|
|
|
|
del outputs[0]
|
|
|
- #print("[OUT] %s" % outputs[0])
|
|
|
+ print("[OUT] %s" % outputs[0])
|
|
|
except:
|
|
|
raise UnknownError()
|
|
|
|
|
@@ -231,7 +228,7 @@ def _last_output():
|
|
|
return outputs[0]
|
|
|
|
|
|
# Raise common exceptions
|
|
|
-def _handle_output(requested=None, split=False):
|
|
|
+def _handle_output(requested=None, split=None):
|
|
|
value = _output()
|
|
|
if value.startswith("Model exists: "):
|
|
|
raise ModelExists(value.split(": ", 1)[1])
|
|
@@ -246,14 +243,14 @@ def _handle_output(requested=None, split=False):
|
|
|
elif value.startswith("Attribute not found: "):
|
|
|
raise NoSuchAttribute(value.split(": ", 1)[1])
|
|
|
elif requested is not None and value.startswith(requested):
|
|
|
- if not split:
|
|
|
+ if split is None:
|
|
|
return value
|
|
|
else:
|
|
|
- splitted = value.strip().split(" ", 1)
|
|
|
- if len(splitted) > 1:
|
|
|
- return splitted[1].split("\n")
|
|
|
+ splitted = value.strip().split(split, 1)
|
|
|
+ if len(splitted) == 1:
|
|
|
+ return ""
|
|
|
else:
|
|
|
- return []
|
|
|
+ return splitted[1].rstrip()
|
|
|
else:
|
|
|
raise InterfaceMismatch(value)
|
|
|
|
|
@@ -299,52 +296,23 @@ def alter_context(model_name, metamodel_name):
|
|
|
registered_metamodels[model_name] = metamodel_name
|
|
|
|
|
|
# Main MvC operations
|
|
|
-def init(address_param="127.0.0.1:8001", timeout=20.0):
|
|
|
+def init(address_param="http://127.0.0.1:8001", timeout=20.0):
|
|
|
"""Starts up the connection to the Modelverse."""
|
|
|
- # Start up the HTTP Client SC
|
|
|
- import http_client
|
|
|
- global ctrl_input
|
|
|
- global ctrl_output
|
|
|
-
|
|
|
- if ctrl_input is not None:
|
|
|
- ctrl_input.stop()
|
|
|
- if ctrl_output is not None:
|
|
|
- ctrl_output.stop()
|
|
|
-
|
|
|
- ctrl_input = http_client.Controller()
|
|
|
- ctrl_output = http_client.Controller()
|
|
|
- controllers = [ctrl_input, ctrl_output]
|
|
|
-
|
|
|
- addr, port = address_param.split(":", 1)
|
|
|
- port = int(port)
|
|
|
-
|
|
|
- for ctrl in controllers:
|
|
|
- listener = ctrl.addOutputListener("request_out")
|
|
|
- socket2event.boot_translation_service(ctrl)
|
|
|
- thrd = threading.Thread(target=ctrl.start)
|
|
|
- thrd.daemon = True
|
|
|
- thrd.start()
|
|
|
-
|
|
|
- evt = listener.fetch(-1)
|
|
|
- if evt.name != "http_client_initialized":
|
|
|
- raise Exception("HTTP client did not behave as expected during init: " + str(evt.name))
|
|
|
-
|
|
|
- ctrl.addInput(Event("connect", "request_in", [(addr, port), timeout]))
|
|
|
-
|
|
|
- evt = listener.fetch(-1)
|
|
|
-
|
|
|
- if evt.name == "http_client_timeout":
|
|
|
- raise Exception("HTTP client timeout")
|
|
|
- if evt.name != "http_client_ready":
|
|
|
- raise Exception("HTTP client did not behave as expected during connect: " + str(evt.name))
|
|
|
-
|
|
|
global mode
|
|
|
+ global address
|
|
|
+ address = address_param
|
|
|
start_time = time.time()
|
|
|
task = random.random()
|
|
|
-
|
|
|
- _input_raw('"%s"' % task, "task_manager")
|
|
|
-
|
|
|
- mode = MODE_UNAUTHORIZED
|
|
|
+ while 1:
|
|
|
+ try:
|
|
|
+ _input_raw('"%s"' % task, "task_manager")
|
|
|
+ mode = MODE_UNAUTHORIZED
|
|
|
+ break
|
|
|
+ except URLError as e:
|
|
|
+ if time.time() - start_time > timeout:
|
|
|
+ raise ConnectionError(e.reason)
|
|
|
+ else:
|
|
|
+ time.sleep(0.1)
|
|
|
|
|
|
global outputs
|
|
|
global taskname
|
|
@@ -431,16 +399,19 @@ def model_list(location):
|
|
|
"""List all models."""
|
|
|
_goto_mode(MODE_MODELLING)
|
|
|
_input(["model_list", location])
|
|
|
- return set(_handle_output("Success: ", split=True))
|
|
|
+ return set(_handle_output("Success: ", split=" ").split("\n"))
|
|
|
|
|
|
def model_list_full(location):
|
|
|
"""List full information on all models."""
|
|
|
_goto_mode(MODE_MODELLING)
|
|
|
_input(["model_list_full", location])
|
|
|
- output = _handle_output("Success: ", split=True)
|
|
|
+ output = _handle_output("Success: ", split=" ")
|
|
|
+ if output == "":
|
|
|
+ return set([])
|
|
|
|
|
|
lst = set([])
|
|
|
- for v in output:
|
|
|
+ value = output.strip().split("\n")
|
|
|
+ for v in value:
|
|
|
m = v.strip()
|
|
|
perm, own, grp, m = m.split(" ", 3)
|
|
|
lst.add((m, own, grp, perm))
|
|
@@ -455,7 +426,7 @@ def verify(model_name, metamodel_name=None):
|
|
|
metamodel_name = _get_metamodel(model_name)
|
|
|
|
|
|
_input(["verify", model_name, metamodel_name])
|
|
|
- return _handle_output("Success: ", split=True)[0]
|
|
|
+ return _handle_output("Success: ", split=" ")
|
|
|
|
|
|
def model_overwrite(model_name, new_model=None, metamodel_name=None):
|
|
|
"""Upload a new model and overwrite an existing model."""
|
|
@@ -497,14 +468,16 @@ def model_render(model_name, mapper_name):
|
|
|
_goto_mode(MODE_MODELLING)
|
|
|
|
|
|
_input(["model_render", model_name, mapper_name])
|
|
|
- return json.loads(_handle_output("Success: ", split=True)[0])
|
|
|
+ return json.loads(_handle_output("Success: ", split=" "))
|
|
|
|
|
|
def transformation_between(source, target):
|
|
|
_goto_mode(MODE_MODELLING)
|
|
|
|
|
|
_input(["transformation_between", source, target])
|
|
|
- output = _handle_output("Success: ", split=True)
|
|
|
- return set(output)
|
|
|
+ output = _handle_output("Success: ", split=" ")
|
|
|
+ if output == "":
|
|
|
+ return set([])
|
|
|
+ return set([v for v in output.split("\n")])
|
|
|
|
|
|
def transformation_add_MT(source_metamodels, target_metamodels, operation_name, code, callback=lambda: None):
|
|
|
"""Create a new model transformation."""
|
|
@@ -666,10 +639,13 @@ def transformation_list():
|
|
|
_goto_mode(MODE_MODELLING)
|
|
|
|
|
|
_input("transformation_list")
|
|
|
- output = _handle_output("Success: ", split=True)
|
|
|
+ output = _handle_output("Success: ", split=" ")
|
|
|
+ if output == "":
|
|
|
+ return set([])
|
|
|
|
|
|
lst = set([])
|
|
|
- for v in output:
|
|
|
+ value = output.strip().split("\n")
|
|
|
+ for v in value:
|
|
|
t, m = v.strip().split(" ", 1)
|
|
|
t = t[1:-1].strip()
|
|
|
m = m.strip().split(":")[0].strip()
|
|
@@ -791,8 +767,10 @@ def element_list(model_name):
|
|
|
|
|
|
_input("list_full")
|
|
|
lst = set([])
|
|
|
- output = _handle_output("Success: ", split=True)
|
|
|
- for v in output:
|
|
|
+ output = _handle_output("Success: ", split=" ")
|
|
|
+ if output == "":
|
|
|
+ return set([])
|
|
|
+ for v in output.split("\n"):
|
|
|
m, mm = v.split(":")
|
|
|
m = m.strip()
|
|
|
mm = mm.strip()
|
|
@@ -805,8 +783,10 @@ def types(model_name):
|
|
|
|
|
|
_input("types")
|
|
|
lst = set([])
|
|
|
- output = _handle_output("Success: ", split=True)
|
|
|
- for v in output:
|
|
|
+ output = _handle_output("Success: ", split=" ")
|
|
|
+ if output == "":
|
|
|
+ return set([])
|
|
|
+ for v in output.split("\n"):
|
|
|
m, mm = v.split(":")
|
|
|
m = m.strip()
|
|
|
lst.add(m)
|
|
@@ -818,8 +798,10 @@ def types_full(model_name):
|
|
|
|
|
|
_input("types")
|
|
|
lst = set([])
|
|
|
- output = _handle_output("Success: ", split=True)
|
|
|
- for v in output:
|
|
|
+ output = _handle_output("Success: ", split=" ")
|
|
|
+ if output == "":
|
|
|
+ return set([])
|
|
|
+ for v in output.split("\n"):
|
|
|
m, mm = v.split(":")
|
|
|
m = m.strip()
|
|
|
mm = mm.strip()
|
|
@@ -831,7 +813,8 @@ def read(model_name, ID):
|
|
|
_goto_mode(MODE_MODIFY, model_name)
|
|
|
|
|
|
_input(["read", ID])
|
|
|
- v = _handle_output("Success: ", split=True)
|
|
|
+ output = _handle_output("Success: ", split=" ")
|
|
|
+ v = output.split("\n")
|
|
|
t = v[1].split(":")[1].strip()
|
|
|
if (not v[2].startswith("Source:")):
|
|
|
rval = (t, None)
|
|
@@ -846,10 +829,11 @@ def read_attrs(model_name, ID):
|
|
|
_goto_mode(MODE_MODIFY, model_name)
|
|
|
|
|
|
_input(["read", ID])
|
|
|
- output = _handle_output("Success: ", split=True)
|
|
|
+ output = _handle_output("Success: ", split=" ")
|
|
|
+ v = output.split("\n")
|
|
|
searching = True
|
|
|
rval = {}
|
|
|
- for r in output:
|
|
|
+ for r in v:
|
|
|
if searching:
|
|
|
if r == "Attributes:":
|
|
|
# Start working on attributes
|
|
@@ -878,7 +862,7 @@ def instantiate(model_name, typename, edge=None, ID=""):
|
|
|
_input(["instantiate_node", typename, ID])
|
|
|
else:
|
|
|
_input(["instantiate_edge", typename, ID, edge[0], edge[1]])
|
|
|
- return _handle_output("Success: ", split=True)[0]
|
|
|
+ return _handle_output("Success: ", split=" ")
|
|
|
|
|
|
def delete_element(model_name, ID):
|
|
|
"""Delete the element with the given ID"""
|
|
@@ -922,30 +906,36 @@ def read_outgoing(model_name, ID, typename):
|
|
|
_goto_mode(MODE_MODIFY, model_name)
|
|
|
|
|
|
_input(["read_outgoing", ID, typename])
|
|
|
- output = _handle_output("Success: ", split=True)
|
|
|
- return set(output)
|
|
|
+ output = _handle_output("Success: ", split=" ")
|
|
|
+ if output == "":
|
|
|
+ return set([])
|
|
|
+ else:
|
|
|
+ return set(output.split("\n"))
|
|
|
|
|
|
def read_incoming(model_name, ID, typename):
|
|
|
"""Returns a list of all incoming associations of a specific type ("" = all)"""
|
|
|
_goto_mode(MODE_MODIFY, model_name)
|
|
|
|
|
|
_input(["read_incoming", ID, typename])
|
|
|
- output = _handle_output("Success: ", split=True)
|
|
|
- return set(output)
|
|
|
+ output = _handle_output("Success: ", split=" ")
|
|
|
+ if output == "":
|
|
|
+ return set([])
|
|
|
+ else:
|
|
|
+ return set(output.split("\n"))
|
|
|
|
|
|
def read_association_source(model_name, ID):
|
|
|
"""Returns the source of an association."""
|
|
|
_goto_mode(MODE_MODIFY, model_name)
|
|
|
|
|
|
_input(["read_association_source", ID])
|
|
|
- return _handle_output("Success: ", split=True)[0]
|
|
|
+ return _handle_output("Success: ", split=" ")
|
|
|
|
|
|
def read_association_destination(model_name, ID):
|
|
|
"""Returns the destination of an association."""
|
|
|
_goto_mode(MODE_MODIFY, model_name)
|
|
|
|
|
|
_input(["read_association_destination", ID])
|
|
|
- return _handle_output("Success: ", split=True)[0]
|
|
|
+ return _handle_output("Success: ", split=" ")
|
|
|
|
|
|
##### To document:
|
|
|
|
|
@@ -965,7 +955,7 @@ def service_register(name, function):
|
|
|
|
|
|
# Now we are in service-mode
|
|
|
mode = MODE_SERVICE
|
|
|
- port = _handle_output("Success: ", split=True)[0]
|
|
|
+ port = _handle_output("Success: ", split=" ")
|
|
|
|
|
|
# Process events in the background!
|
|
|
threading.Thread(target=service_process, args=[port]).start()
|
|
@@ -1006,7 +996,7 @@ def element_list_nice(model_name):
|
|
|
|
|
|
_input(["element_list_nice", model_name, _get_metamodel(model_name)])
|
|
|
|
|
|
- data = _handle_output("Success: ", split=True)[0]
|
|
|
+ data = _handle_output("Success: ", split=" ")
|
|
|
try:
|
|
|
return json.loads(data)
|
|
|
except:
|
|
@@ -1018,23 +1008,29 @@ def connections_between(model_name, source_element, target_element):
|
|
|
_goto_mode(MODE_MODIFY, model_name)
|
|
|
|
|
|
_input(["connections_between", source_element, target_element])
|
|
|
- output = _handle_output("Success: ", split=True)
|
|
|
- return set(output)
|
|
|
+ output = _handle_output("Success: ", split=" ")
|
|
|
+ if output == "":
|
|
|
+ return set([])
|
|
|
+ else:
|
|
|
+ return set(output.split("\n"))
|
|
|
|
|
|
def define_attribute(model_name, node, attr_name, attr_type):
|
|
|
"""Create a new attribute, which can be instantiated one meta-level below."""
|
|
|
_goto_mode(MODE_MODIFY, model_name)
|
|
|
|
|
|
_input(["define_attribute", node, attr_name, attr_type])
|
|
|
- return _handle_output("Success: ", split=True)[0]
|
|
|
+ return _handle_output("Success: ", split=" ")
|
|
|
|
|
|
def all_instances(model_name, type_name):
|
|
|
"""Returns a list of all elements of a specific type."""
|
|
|
_goto_mode(MODE_MODIFY, model_name)
|
|
|
|
|
|
_input(["all_instances", type_name])
|
|
|
- output = _handle_output("Success: ", split=True)
|
|
|
- return set(output)
|
|
|
+ output = _handle_output("Success: ", split=" ")
|
|
|
+ if output == "":
|
|
|
+ return set([])
|
|
|
+ else:
|
|
|
+ return set(output.split("\n"))
|
|
|
|
|
|
def service_poll(port):
|
|
|
"""Checks whether or not the Modelverse side has any input ready to be processed."""
|