|
@@ -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,12 +64,11 @@ 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):
|
|
|
while taskname is None:
|
|
@@ -80,6 +81,38 @@ 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]
|
|
|
+
|
|
|
+ print("Sending MV event: " + str(output_event))
|
|
|
+ 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
|
|
|
+ print("Got SC event: " + str(input_event))
|
|
|
+ _input(input_event)
|
|
|
+
|
|
|
+ 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
|
|
|
try:
|
|
@@ -129,7 +162,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([])):
|
|
@@ -182,22 +215,20 @@ def _compile_model(code):
|
|
|
|
|
|
def _output(expected=None):
|
|
|
try:
|
|
|
- global last_output
|
|
|
-
|
|
|
- while not outputs:
|
|
|
+ while len(outputs) < 2:
|
|
|
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):
|
|
@@ -529,31 +560,18 @@ def transformation_execute_AL(operation_name, input_models_dict, output_models_d
|
|
|
_handle_output("Success: ready for AL execution")
|
|
|
|
|
|
if statechart is not None:
|
|
|
- inputs = [None]
|
|
|
- outputs = [None]
|
|
|
- thrd = threading.Thread(target=exec_statechart, args=[statechart, inputs, outputs])
|
|
|
- thrd.daemon = True
|
|
|
- thrd.start()
|
|
|
-
|
|
|
- # On this remote thread, we are running the statechart, producing output and consuming input
|
|
|
- # We bind to this input and output by passing references to the function, which it must update to reflect the input/output queue
|
|
|
-
|
|
|
- while 1:
|
|
|
- # Poll for outputs to send
|
|
|
- try:
|
|
|
- outp = outputs[0].fetch(0)
|
|
|
- print("Got SC output: " + str(outp))
|
|
|
- _input(outp)
|
|
|
- except Queue.Empty:
|
|
|
- if not thrd.is_alive():
|
|
|
- # No more outputs, and the SC is not even alive anymore, so stop
|
|
|
- break
|
|
|
-
|
|
|
- # Got termination message, so we are done!
|
|
|
- if _output() == "Success":
|
|
|
- return True
|
|
|
+ # 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
|
|
|
+ _exec_on_statechart(statechart)
|
|
|
+ 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."""
|
|
@@ -592,19 +610,19 @@ 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"]:
|
|
|
- mode = MODE_DIALOG
|
|
|
- reply = callback(_last_output())
|
|
|
- mode = MODE_MODELLING
|
|
|
- if reply is not None:
|
|
|
- _input(reply)
|
|
|
-
|
|
|
- # Got termination message, so we are done!
|
|
|
- if _last_output() == "Success":
|
|
|
- return True
|
|
|
+ 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
|
|
|
+ _exec_on_statechart(statechart)
|
|
|
+ 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."""
|