|
@@ -8,6 +8,8 @@ import time
|
|
|
import threading
|
|
|
import Queue
|
|
|
|
|
|
+from sccd.runtime.statecharts_core import Event
|
|
|
+
|
|
|
COMPILER_PATH = "interface/HUTN"
|
|
|
|
|
|
MODE_UNCONNECTED = 0
|
|
@@ -62,14 +64,13 @@ class UnknownMetamodellingHierarchy(ModelverseException):
|
|
|
# Helper functions and configuration: do not use yourself!
|
|
|
taskname = None
|
|
|
address = None
|
|
|
-last_output = None
|
|
|
mode = MODE_UNCONNECTED
|
|
|
prev_mode = None
|
|
|
current_model = None
|
|
|
registered_metamodels = {}
|
|
|
-outputs = []
|
|
|
+outputs = [None]
|
|
|
|
|
|
-def _output_thread(outputs):
|
|
|
+def _output_thread(outputs, taskname):
|
|
|
while taskname is None:
|
|
|
time.sleep(0.1)
|
|
|
|
|
@@ -79,9 +80,36 @@ def _output_thread(outputs):
|
|
|
except:
|
|
|
pass
|
|
|
|
|
|
-thrd = threading.Thread(target=_output_thread, args=[outputs])
|
|
|
-thrd.daemon = True
|
|
|
-thrd.start()
|
|
|
+def _exec_on_statechart(statechart):
|
|
|
+ def _exec_sc(controller, inport, outport):
|
|
|
+ op = controller.addOutputListener(outport)
|
|
|
+
|
|
|
+ while 1:
|
|
|
+ if len(outputs) > 1:
|
|
|
+ # Is an output message of the Mv, so put it in the SC
|
|
|
+ del outputs[0]
|
|
|
+ output_event = outputs[0]
|
|
|
+
|
|
|
+ if output_event == "Success" or output_event == "Failure":
|
|
|
+ # Is a stop event!
|
|
|
+ controller.addInput(Event("terminate", inport, []))
|
|
|
+ break
|
|
|
+ else:
|
|
|
+ # Is just a normal event!
|
|
|
+ controller.addInput(Event("input", inport, [output_event]))
|
|
|
+
|
|
|
+ input_event = op.fetch(0)
|
|
|
+ if input_event is not None:
|
|
|
+ # Expand the event and make it HTTP input
|
|
|
+ _input(input_event.parameters)
|
|
|
+
|
|
|
+ time.sleep(0.01)
|
|
|
+
|
|
|
+ thrd = threading.Thread(target=_exec_sc, args=statechart)
|
|
|
+ thrd.daemon = True
|
|
|
+ thrd.start()
|
|
|
+
|
|
|
+ return None
|
|
|
|
|
|
def _get_metamodel(model):
|
|
|
global registered_metamodels
|
|
@@ -132,7 +160,7 @@ 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([])):
|
|
@@ -147,8 +175,6 @@ def _input_raw(value, taskname):
|
|
|
# Ugly json encoding of primitives
|
|
|
urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "value": value, "taskname": taskname}))).read()
|
|
|
|
|
|
- #TODO check that this is actually a Modelverse!
|
|
|
-
|
|
|
def _compile_AL(code):
|
|
|
# Compile an action language file and send the compiled code
|
|
|
code_fragments = code.split("\n")
|
|
@@ -185,22 +211,21 @@ def _compile_model(code):
|
|
|
|
|
|
def _output(expected=None):
|
|
|
try:
|
|
|
- global last_output
|
|
|
+ while len(outputs) < 2:
|
|
|
+ time.sleep(0.5)
|
|
|
+ print("Sleep for output: " + str(outputs))
|
|
|
|
|
|
- while not outputs:
|
|
|
- time.sleep(0.01)
|
|
|
-
|
|
|
- last_output = outputs.pop(0)
|
|
|
- #print("[OUT] %s" % last_output)
|
|
|
+ del outputs[0]
|
|
|
+ print("[OUT] %s" % outputs[0])
|
|
|
except:
|
|
|
raise UnknownError()
|
|
|
|
|
|
- if expected is not None and last_output != expected:
|
|
|
+ if expected is not None and _last_output() != expected:
|
|
|
raise InterfaceMismatch(_last_output(), expected)
|
|
|
- return last_output
|
|
|
+ return _last_output()
|
|
|
|
|
|
def _last_output():
|
|
|
- return last_output
|
|
|
+ return outputs[0]
|
|
|
|
|
|
# Raise common exceptions
|
|
|
def _handle_output(requested=None, split=None):
|
|
@@ -288,9 +313,18 @@ def init(address_param="http://127.0.0.1:8001", timeout=20.0):
|
|
|
raise ConnectionError(e.reason)
|
|
|
else:
|
|
|
time.sleep(0.1)
|
|
|
+
|
|
|
+ global outputs
|
|
|
global taskname
|
|
|
+
|
|
|
+ outputs = [None]
|
|
|
taskname = task
|
|
|
|
|
|
+ # This re-assign also diconnects the previous get_output connections to the outputs variable
|
|
|
+ thrd = threading.Thread(target=_output_thread, args=[outputs, task])
|
|
|
+ thrd.daemon = True
|
|
|
+ thrd.start()
|
|
|
+
|
|
|
def login(username, password):
|
|
|
"""Log in a user, if user doesn't exist, it is created."""
|
|
|
global mode
|
|
@@ -521,7 +555,7 @@ def transformation_add_MANUAL(source_metamodels, target_metamodels, operation_na
|
|
|
|
|
|
_handle_output("Success")
|
|
|
|
|
|
-def transformation_execute_AL(operation_name, input_models_dict, output_models_dict, callback=lambda i: None):
|
|
|
+def transformation_execute_AL(operation_name, input_models_dict, output_models_dict, statechart=None):
|
|
|
"""Execute an existing model operation."""
|
|
|
global mode
|
|
|
_goto_mode(MODE_MODELLING)
|
|
@@ -531,19 +565,21 @@ def transformation_execute_AL(operation_name, input_models_dict, output_models_d
|
|
|
_input(["transformation_execute", operation_name] + mv_dict_rep)
|
|
|
_handle_output("Success: ready for AL execution")
|
|
|
|
|
|
- # We are now executing, so everything we get is part of the dialog, except if it is the string for transformation termination
|
|
|
- while _output() not in ["Success", "Failure"]:
|
|
|
+ if statechart is not None:
|
|
|
+ # We are to delegate this information to another statechart, which wants interaction
|
|
|
+ # As such, we continue on a different thread, where we pipe the information, and let this call return immediately
|
|
|
mode = MODE_DIALOG
|
|
|
- reply = callback(_last_output())
|
|
|
+ _exec_on_statechart(statechart)
|
|
|
mode = MODE_MODELLING
|
|
|
- if reply is not None:
|
|
|
- _input(reply)
|
|
|
-
|
|
|
- # Got termination message, so we are done!
|
|
|
- if _last_output() == "Success":
|
|
|
- return True
|
|
|
+ return None
|
|
|
else:
|
|
|
- return False
|
|
|
+ # No statechart associated, so just wait until we are finished
|
|
|
+ while _output() not in ["Success", "Failure"]:
|
|
|
+ pass
|
|
|
+ if _last_output() == "Success":
|
|
|
+ return True
|
|
|
+ else:
|
|
|
+ return False
|
|
|
|
|
|
def transformation_execute_MANUAL(operation_name, input_models_dict, output_models_dict, callback=lambda i: None):
|
|
|
"""Execute an existing model operation."""
|
|
@@ -572,7 +608,7 @@ def transformation_execute_MANUAL(operation_name, input_models_dict, output_mode
|
|
|
else:
|
|
|
return False
|
|
|
|
|
|
-def transformation_execute_MT(operation_name, input_models_dict, output_models_dict, callback=lambda i: None):
|
|
|
+def transformation_execute_MT(operation_name, input_models_dict, output_models_dict, statechart=None):
|
|
|
"""Execute an existing model operation."""
|
|
|
global mode
|
|
|
_goto_mode(MODE_MODELLING)
|
|
@@ -582,19 +618,21 @@ def transformation_execute_MT(operation_name, input_models_dict, output_models_d
|
|
|
_input(["transformation_execute", operation_name] + mv_dict_rep)
|
|
|
_handle_output("Success: ready for MT execution")
|
|
|
|
|
|
- # We are now executing, so everything we get is part of the dialog, except if it is the string for transformation termination
|
|
|
- while _output() not in ["Success", "Failure"]:
|
|
|
+ if statechart is not None:
|
|
|
+ # We are to delegate this information to another statechart, which wants interaction
|
|
|
+ # As such, we continue on a different thread, where we pipe the information, and let this call return immediately
|
|
|
mode = MODE_DIALOG
|
|
|
- reply = callback(_last_output())
|
|
|
+ _exec_on_statechart(statechart)
|
|
|
mode = MODE_MODELLING
|
|
|
- if reply is not None:
|
|
|
- _input(reply)
|
|
|
-
|
|
|
- # Got termination message, so we are done!
|
|
|
- if _last_output() == "Success":
|
|
|
- return True
|
|
|
+ return None
|
|
|
else:
|
|
|
- return False
|
|
|
+ # No statechart associated, so just wait until we are finished
|
|
|
+ while _output() not in ["Success", "Failure"]:
|
|
|
+ pass
|
|
|
+ if _last_output() == "Success":
|
|
|
+ return True
|
|
|
+ else:
|
|
|
+ return False
|
|
|
|
|
|
def transformation_list():
|
|
|
"""List existing model operations."""
|