|
@@ -0,0 +1,342 @@
|
|
|
+<class name="Modelverse">
|
|
|
+ <relationships>
|
|
|
+ <association name="http_client" class="HTTPClient" min="2" max="2"/>
|
|
|
+ </relationships>
|
|
|
+
|
|
|
+ <method name="load_action">
|
|
|
+ <parameter name="context"/>
|
|
|
+ <body>
|
|
|
+ action = self.actions[None].pop(0)
|
|
|
+ self.parameters = action["parameters"]
|
|
|
+ self.current_ID = action["ID"]
|
|
|
+ </body>
|
|
|
+ </method>
|
|
|
+
|
|
|
+ <method name="expect_response">
|
|
|
+ <parameter name="expected"/>
|
|
|
+ <parameter name="pop" default="False"/>
|
|
|
+ <body>
|
|
|
+ if self.responses and self.responses[0] == expected:
|
|
|
+ if pop:
|
|
|
+ del self.responses[0]
|
|
|
+ return True
|
|
|
+ else:
|
|
|
+ return False
|
|
|
+ </body>
|
|
|
+ </method>
|
|
|
+
|
|
|
+ <method name="expect_action">
|
|
|
+ <parameter name="context"/>
|
|
|
+ <parameter name="expected"/>
|
|
|
+ <body>
|
|
|
+ return self.actions[context] and self.actions[context][0]["name"] == expected
|
|
|
+ </body>
|
|
|
+ </method>
|
|
|
+
|
|
|
+ <constructor>
|
|
|
+ <body>
|
|
|
+ self.actions = {None: []}
|
|
|
+ self.responses = []
|
|
|
+ self.http_clients = []
|
|
|
+ </body>
|
|
|
+ </constructor>
|
|
|
+
|
|
|
+ <scxml initial="init">
|
|
|
+ <state id="init">
|
|
|
+ <onentry>
|
|
|
+ <raise scope="cd" event="create_instance">
|
|
|
+ <parameter expr="'http_client'"/>
|
|
|
+ <parameter expr="'HTTPClient'"/>
|
|
|
+ </raise>
|
|
|
+
|
|
|
+ <raise scope="cd" event="create_instance">
|
|
|
+ <parameter expr="'http_client'"/>
|
|
|
+ <parameter expr="'HTTPClient'"/>
|
|
|
+ </raise>
|
|
|
+ </onentry>
|
|
|
+
|
|
|
+ <transition event="instance_created" target=".">
|
|
|
+ <parameter name="instance"/>
|
|
|
+ <script>
|
|
|
+ self.http_clients.append(instance)
|
|
|
+ </script>
|
|
|
+ <raise scope="cd" event="start_instance">
|
|
|
+ <parameter expr="instance"/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+
|
|
|
+ <transition cond="len(self.http_clients) == 2" target="../waiting"/>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="waiting">
|
|
|
+ <transition event="http_client_initialized" target="../initialized"/>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <parallel id="initialized">
|
|
|
+ <onentry>
|
|
|
+ <raise scope="output" port="ready" event="ready"/>
|
|
|
+ </onentry>
|
|
|
+
|
|
|
+ <state id="http_mapper" initial="init">
|
|
|
+ <state id="init">
|
|
|
+ <transition event="request" cond="isinstance(value, type([]))" target=".">
|
|
|
+ <parameter name="value"/>
|
|
|
+ <raise event="HTTP_input" target="self.http_clients[0]">
|
|
|
+ <parameter expr='urllib.urlencode({"op": "set_input", "data": json.dumps(value), "taskname": self.taskname})'/>
|
|
|
+ <parameter expr='None'/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+
|
|
|
+ <transition event="request" cond="not isinstance(value, type([]))" target=".">
|
|
|
+ <parameter name="value"/>
|
|
|
+ <raise event="HTTP_input" target="self.http_clients[0]">
|
|
|
+ <parameter expr='urllib.urlencode({"op": "set_input", "value": json.dumps(value), "taskname": self.taskname})'/>
|
|
|
+ <parameter expr='None'/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+
|
|
|
+ <transition event="request_raw" target=".">
|
|
|
+ <parameter name="value"/>
|
|
|
+ <parameter name="taskname"/>
|
|
|
+ <parameter name="http_client"/>
|
|
|
+ <raise event="HTTP_input" target="self.http_clients[http_client]">
|
|
|
+ <parameter expr='urllib.urlencode({"op": "set_input", "value": json.dumps(value), "taskname": taskname})'/>
|
|
|
+ <parameter expr='"parent"'/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+
|
|
|
+ <transition event="HTTP_output" target=".">
|
|
|
+ <parameter name="data"/>
|
|
|
+ <raise event="HTTP_input" target="self.http_clients[1]">
|
|
|
+ <parameter expr='urllib.urlencode({"op": "get_output", "taskname": self.taskname})'/>
|
|
|
+ <parameter expr='"parent"'/>
|
|
|
+ </raise>
|
|
|
+ <script>
|
|
|
+ print("Got output " + str(data))
|
|
|
+ self.responses.append(json.loads(data))
|
|
|
+ </script>
|
|
|
+ </transition>
|
|
|
+ </state>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="behaviour" initial="wait_for_action">
|
|
|
+ <state id="connecting" initial="connect_http_client">
|
|
|
+ <onentry>
|
|
|
+ <script>
|
|
|
+ self.address, self.timeout = self.parameters
|
|
|
+ self.address = self.address.rsplit(":", 1)
|
|
|
+ self.address = (self.address[0], int(self.address[1]))
|
|
|
+
|
|
|
+ self.i = 0
|
|
|
+ self.taskname = str(uuid.uuid4())
|
|
|
+ </script>
|
|
|
+ </onentry>
|
|
|
+
|
|
|
+ <state id="connect_http_client">
|
|
|
+ <transition cond="self.i < 2" target="../waiting_http_client">
|
|
|
+ <raise scope="narrow" target="self.http_clients[self.i]" event="connect">
|
|
|
+ <parameter expr="self.address"/>
|
|
|
+ <parameter expr="self.timeout"/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+
|
|
|
+ <transition cond="self.i == 2" target="../../wait_for_action/connected">
|
|
|
+ <!-- Start polling for output -->
|
|
|
+ <raise event="HTTP_input" target="self.http_clients[1]">
|
|
|
+ <parameter expr='urllib.urlencode({"op": "get_output", "taskname": self.taskname})'/>
|
|
|
+ <parameter expr='"parent"'/>
|
|
|
+ </raise>
|
|
|
+
|
|
|
+ <!-- Sent out completion -->
|
|
|
+ <raise event="result">
|
|
|
+ <parameter expr="[]"/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="waiting_http_client">
|
|
|
+ <transition event="http_client_ready" target="../wait_for_taskname_ack">
|
|
|
+ <!-- Request the task to be created -->
|
|
|
+ <raise event="request_raw">
|
|
|
+ <parameter expr="self.taskname"/>
|
|
|
+ <parameter expr="'task_manager'"/>
|
|
|
+ <parameter expr="self.i"/>
|
|
|
+ </raise>
|
|
|
+
|
|
|
+ <script>
|
|
|
+ self.i += 1
|
|
|
+ </script>
|
|
|
+ </transition>
|
|
|
+
|
|
|
+ <transition event="http_client_timeout" target="../../wait_for_action/disconnected">
|
|
|
+ <raise scope="broad" event="exception">
|
|
|
+ <parameter expr="self.current_ID"/>
|
|
|
+ <parameter expr="'Connection timeout'"/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="wait_for_taskname_ack">
|
|
|
+ <transition cond="self.expect_response('OK', pop=True)" target="../connect_http_client"/>
|
|
|
+ </state>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="logging_in" initial="wait_prompt_1">
|
|
|
+ <state id="wait_prompt_1">
|
|
|
+ <transition cond="self.expect_response('Log on as which user?', pop=True)" target="../wait_prompt_2">
|
|
|
+ <raise event="request">
|
|
|
+ <parameter expr="self.parameters[0]"/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="wait_prompt_2">
|
|
|
+ <transition cond="self.expect_response('Password for existing user?', pop=True)" target="../wait_prompt_existing">
|
|
|
+ <raise event="request">
|
|
|
+ <parameter expr="self.parameters[1]"/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+
|
|
|
+ <transition cond="self.expect_response('This is a new user: please give password!', pop=True)" target="../wait_prompt_existing">
|
|
|
+ <raise event="request">
|
|
|
+ <parameter expr="self.parameters[1]"/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="wait_prompt_existing">
|
|
|
+ <transition cond="self.expect_response('Welcome to the Model Management Interface v2.0!', pop=True)" target="../login_ok"/>
|
|
|
+ <transition cond="self.expect_response('Wrong password!', pop=True)" target="../../wait_for_action/connected">
|
|
|
+ <raise event="exception">
|
|
|
+ <parameter expr="{'name': 'PermissionDenied'}"/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="login_ok">
|
|
|
+ <transition cond="self.expect_response('Use the \'help\' command for a list of possible commands', pop=True)" target="../../wait_for_action/megamodelling">
|
|
|
+ <raise event="request">
|
|
|
+ <parameter expr="'quiet'"/>
|
|
|
+ </raise>
|
|
|
+ <raise event="result">
|
|
|
+ <parameter expr="[]"/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+ </state>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="model_add" initial="init">
|
|
|
+ <state id="init">
|
|
|
+ <transition cond="self.parameters[2] is not None" target="../compiled">
|
|
|
+ <script>
|
|
|
+ try:
|
|
|
+ self.compiled = _compile_model(model_code)
|
|
|
+ self.exception = None
|
|
|
+ except Exception as e:
|
|
|
+ self.compiled = None
|
|
|
+ self.exception = e
|
|
|
+ </script>
|
|
|
+ </transition>
|
|
|
+ <transition cond="self.parameters[2] is None" target="../compiled">
|
|
|
+ <script>
|
|
|
+ self.compiled = [0]
|
|
|
+ self.exception = None
|
|
|
+ </script>
|
|
|
+ </transition>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="compiled">
|
|
|
+ <transition cond="self.compiled is None" target="../../wait_for_action/history">
|
|
|
+ <raise event="exception">
|
|
|
+ <parameter expr="self.exception"/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+
|
|
|
+ <transition cond="self.compiled is not None" target="../sent_commands">
|
|
|
+ <raise event="request">
|
|
|
+ <parameter expr="['model_add', self.parameters[1], self.parameters[0]]"/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="sent_commands">
|
|
|
+ <transition cond="self.expect_response('Waiting for model constructors')">
|
|
|
+ </state>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="wait_for_action" initial="disconnected">
|
|
|
+ <state id="disconnected">
|
|
|
+ <transition cond="self.expect_action(None, 'init')" target="../../connecting">
|
|
|
+ <script>
|
|
|
+ self.load_action(None)
|
|
|
+ </script>
|
|
|
+ </transition>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="connected">
|
|
|
+ <transition cond="self.expect_action(None, 'login')" target="../../logging_in">
|
|
|
+ <script>
|
|
|
+ self.load_action(None)
|
|
|
+ </script>
|
|
|
+ </transition>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="megamodelling">
|
|
|
+ <transition cond="self.expect_action(None, 'model_add')" target="../../model_add">
|
|
|
+ <script>
|
|
|
+ self.load_action(None)
|
|
|
+ </script>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="modelling" initial="manual">
|
|
|
+ <state id="manual">
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="scripted">
|
|
|
+ </state>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <history id="history" type="deep"/>
|
|
|
+ </state>
|
|
|
+ </state>
|
|
|
+
|
|
|
+ <state id="queue">
|
|
|
+ <state id="queue">
|
|
|
+ <transition port="action_in" event="action" target=".">
|
|
|
+ <parameter name="action_name"/>
|
|
|
+ <parameter name="ID"/>
|
|
|
+ <parameter name="context_ID"/>
|
|
|
+ <parameter name="parameters"/>
|
|
|
+ <script>
|
|
|
+ self.actions[context_ID].append({"name": action_name, "ID": ID, "parameters": parameters})
|
|
|
+ </script>
|
|
|
+ </transition>
|
|
|
+
|
|
|
+ <transition event="result" target=".">
|
|
|
+ <parameter name="parameters"/>
|
|
|
+ <raise scope="output" event="result" port="action_out">
|
|
|
+ <parameter expr="self.current_ID"/>
|
|
|
+ <parameter expr="parameters"/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+
|
|
|
+ <transition event="exception" target=".">
|
|
|
+ <parameter name="parameters"/>
|
|
|
+ <raise scope="output" event="exception" port="action_out">
|
|
|
+ <parameter expr="self.current_ID"/>
|
|
|
+ <parameter expr="parameters"/>
|
|
|
+ </raise>
|
|
|
+ </transition>
|
|
|
+
|
|
|
+ <transition port="input_in" event="input" target=".">
|
|
|
+ <parameter name="value"/>
|
|
|
+ <parameter name="context_ID"/>
|
|
|
+ <script>
|
|
|
+ self.inputs[context_ID].append(value)
|
|
|
+ </script>
|
|
|
+ </transition>
|
|
|
+ </state>
|
|
|
+ </state>
|
|
|
+ </parallel>
|
|
|
+ </scxml>
|
|
|
+</class>
|