modelverse.xml 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. <class name="Modelverse">
  2. <relationships>
  3. <association name="http_client" class="HTTPClient" min="2" max="2"/>
  4. </relationships>
  5. <method name="load_action">
  6. <parameter name="context"/>
  7. <body>
  8. action = self.actions[None].pop(0)
  9. self.parameters = action["parameters"]
  10. self.current_ID = action["ID"]
  11. </body>
  12. </method>
  13. <method name="split_response">
  14. <parameter name="response"/>
  15. <body>
  16. splitted = response.strip().split(": ", 1)
  17. if len(splitted) > 1:
  18. return splitted[1].split("\n")
  19. else:
  20. return []
  21. </body>
  22. </method>
  23. <method name="expect_response">
  24. <parameter name="expected"/>
  25. <parameter name="pop" default="False"/>
  26. <body>
  27. if self.responses and self.responses[0] == expected:
  28. if pop:
  29. del self.responses[0]
  30. return True
  31. else:
  32. return False
  33. </body>
  34. </method>
  35. <method name="expect_response_partial">
  36. <parameter name="expected"/>
  37. <parameter name="pop" default="False"/>
  38. <body>
  39. if self.responses and self.responses[0].startswith(expected):
  40. if pop:
  41. del self.responses[0]
  42. return True
  43. else:
  44. return False
  45. </body>
  46. </method>
  47. <method name="expect_action">
  48. <parameter name="context"/>
  49. <parameter name="expected"/>
  50. <body>
  51. return self.actions[context] and self.actions[context][0]["name"] == expected
  52. </body>
  53. </method>
  54. <constructor>
  55. <body>
  56. self.actions = {None: []}
  57. self.responses = []
  58. self.http_clients = []
  59. </body>
  60. </constructor>
  61. <scxml initial="init">
  62. <state id="init">
  63. <onentry>
  64. <raise scope="cd" event="create_instance">
  65. <parameter expr="'http_client'"/>
  66. <parameter expr="'HTTPClient'"/>
  67. </raise>
  68. <raise scope="cd" event="create_instance">
  69. <parameter expr="'http_client'"/>
  70. <parameter expr="'HTTPClient'"/>
  71. </raise>
  72. </onentry>
  73. <transition event="instance_created" target=".">
  74. <parameter name="instance"/>
  75. <script>
  76. self.http_clients.append(instance)
  77. </script>
  78. <raise scope="cd" event="start_instance">
  79. <parameter expr="instance"/>
  80. </raise>
  81. </transition>
  82. <transition cond="len(self.http_clients) == 2" target="../waiting"/>
  83. </state>
  84. <state id="waiting">
  85. <transition event="http_client_initialized" target="../initialized"/>
  86. </state>
  87. <parallel id="initialized">
  88. <onentry>
  89. <raise scope="output" port="ready" event="ready"/>
  90. </onentry>
  91. <state id="http_mapper" initial="init">
  92. <state id="init">
  93. <transition event="request" cond="isinstance(value, type([]))" target=".">
  94. <parameter name="value"/>
  95. <raise event="HTTP_input" target="self.http_clients[0]">
  96. <parameter expr='urllib.urlencode({"op": "set_input", "data": json.dumps(value), "taskname": self.taskname})'/>
  97. <parameter expr='None'/>
  98. </raise>
  99. </transition>
  100. <transition event="request" cond="not isinstance(value, type([]))" target=".">
  101. <parameter name="value"/>
  102. <raise event="HTTP_input" target="self.http_clients[0]">
  103. <parameter expr='urllib.urlencode({"op": "set_input", "value": json.dumps(value), "taskname": self.taskname})'/>
  104. <parameter expr='None'/>
  105. </raise>
  106. </transition>
  107. <transition event="request_raw" target=".">
  108. <parameter name="value"/>
  109. <parameter name="taskname"/>
  110. <parameter name="http_client"/>
  111. <raise event="HTTP_input" target="self.http_clients[http_client]">
  112. <parameter expr='urllib.urlencode({"op": "set_input", "value": json.dumps(value), "taskname": taskname})'/>
  113. <parameter expr='"parent"'/>
  114. </raise>
  115. </transition>
  116. <transition event="HTTP_output" target=".">
  117. <parameter name="data"/>
  118. <raise event="HTTP_input" target="self.http_clients[1]">
  119. <parameter expr='urllib.urlencode({"op": "get_output", "taskname": self.taskname})'/>
  120. <parameter expr='"parent"'/>
  121. </raise>
  122. <script>
  123. self.responses.append(json.loads(data))
  124. </script>
  125. </transition>
  126. </state>
  127. </state>
  128. <state id="behaviour" initial="wait_for_action">
  129. <state id="connecting" initial="connect_http_client">
  130. <onentry>
  131. <script>
  132. self.address, self.timeout = self.parameters
  133. self.address = self.address.rsplit(":", 1)
  134. self.address = (self.address[0], int(self.address[1]))
  135. self.i = 0
  136. self.taskname = str(uuid.uuid4())
  137. </script>
  138. </onentry>
  139. <state id="connect_http_client">
  140. <transition cond="self.i &lt; 2" target="../waiting_http_client">
  141. <raise scope="narrow" target="self.http_clients[self.i]" event="connect">
  142. <parameter expr="self.address"/>
  143. <parameter expr="self.timeout"/>
  144. </raise>
  145. </transition>
  146. <transition cond="self.i == 2" target="../../wait_for_action/connected">
  147. <!-- Start polling for output -->
  148. <raise event="HTTP_input" target="self.http_clients[1]">
  149. <parameter expr='urllib.urlencode({"op": "get_output", "taskname": self.taskname})'/>
  150. <parameter expr='"parent"'/>
  151. </raise>
  152. <!-- Sent out completion -->
  153. <raise event="result">
  154. <parameter expr="[]"/>
  155. </raise>
  156. </transition>
  157. </state>
  158. <state id="waiting_http_client">
  159. <transition event="http_client_ready" target="../wait_for_taskname_ack">
  160. <!-- Request the task to be created -->
  161. <raise event="request_raw">
  162. <parameter expr="self.taskname"/>
  163. <parameter expr="'task_manager'"/>
  164. <parameter expr="self.i"/>
  165. </raise>
  166. <script>
  167. self.i += 1
  168. </script>
  169. </transition>
  170. <transition event="http_client_timeout" target="../../wait_for_action/disconnected">
  171. <raise scope="broad" event="exception">
  172. <parameter expr="self.current_ID"/>
  173. <parameter expr="'Connection timeout'"/>
  174. </raise>
  175. </transition>
  176. </state>
  177. <state id="wait_for_taskname_ack">
  178. <transition cond="self.expect_response('OK', pop=True)" target="../connect_http_client"/>
  179. </state>
  180. </state>
  181. <state id="logging_in" initial="wait_prompt_1">
  182. <state id="wait_prompt_1">
  183. <transition cond="self.expect_response('Log on as which user?', pop=True)" target="../wait_prompt_2">
  184. <raise event="request">
  185. <parameter expr="self.parameters[0]"/>
  186. </raise>
  187. </transition>
  188. </state>
  189. <state id="wait_prompt_2">
  190. <transition cond="self.expect_response('Password for existing user?', pop=True)" target="../wait_prompt_existing">
  191. <raise event="request">
  192. <parameter expr="self.parameters[1]"/>
  193. </raise>
  194. </transition>
  195. <transition cond="self.expect_response('This is a new user: please give password!', pop=True)" target="../wait_prompt_existing">
  196. <raise event="request">
  197. <parameter expr="self.parameters[1]"/>
  198. </raise>
  199. </transition>
  200. </state>
  201. <state id="wait_prompt_existing">
  202. <transition cond="self.expect_response('Welcome to the Model Management Interface v2.0!', pop=True)" target="../login_ok"/>
  203. <transition cond="self.expect_response('Wrong password!', pop=True)" target="../../wait_for_action/connected">
  204. <raise event="exception">
  205. <parameter expr="{'name': 'PermissionDenied'}"/>
  206. </raise>
  207. </transition>
  208. </state>
  209. <state id="login_ok">
  210. <transition cond="self.expect_response('Use the \'help\' command for a list of possible commands', pop=True)" target="../../wait_for_action/megamodelling">
  211. <raise event="request">
  212. <parameter expr="'quiet'"/>
  213. </raise>
  214. <raise event="result">
  215. <parameter expr="None"/>
  216. </raise>
  217. </transition>
  218. </state>
  219. </state>
  220. <state id="model_list">
  221. <onentry>
  222. <raise event="request">
  223. <parameter expr="['model_list', self.parameters[0]]"/>
  224. </raise>
  225. </onentry>
  226. <transition cond="self.expect_response_partial('Success: ', pop=False)" target="../wait_for_action/history">
  227. <raise event="result">
  228. <parameter expr="self.split_response(self.responses.pop(0))"/>
  229. </raise>
  230. </transition>
  231. </state>
  232. <state id="wait_for_action" initial="disconnected">
  233. <state id="disconnected">
  234. <transition cond="self.expect_action(None, 'init')" target="../../connecting">
  235. <script>
  236. self.load_action(None)
  237. </script>
  238. </transition>
  239. </state>
  240. <state id="connected">
  241. <transition cond="self.expect_action(None, 'login')" target="../../logging_in">
  242. <script>
  243. self.load_action(None)
  244. </script>
  245. </transition>
  246. </state>
  247. <state id="megamodelling">
  248. <transition cond="self.expect_action(None, 'model_list')" target="../../model_list">
  249. <script>
  250. self.load_action(None)
  251. </script>
  252. </transition>
  253. </state>
  254. <state id="modelling" initial="manual">
  255. <state id="manual">
  256. </state>
  257. <state id="scripted">
  258. </state>
  259. </state>
  260. <history id="history" type="deep"/>
  261. </state>
  262. </state>
  263. <state id="queue">
  264. <state id="queue">
  265. <transition port="action_in" event="action" target=".">
  266. <parameter name="action_name"/>
  267. <parameter name="ID"/>
  268. <parameter name="context_ID"/>
  269. <parameter name="parameters"/>
  270. <script>
  271. self.actions[context_ID].append({"name": action_name, "ID": ID, "parameters": parameters})
  272. </script>
  273. </transition>
  274. <transition event="result" target=".">
  275. <parameter name="parameters"/>
  276. <raise scope="output" event="result" port="action_out">
  277. <parameter expr="self.current_ID"/>
  278. <parameter expr="parameters"/>
  279. </raise>
  280. </transition>
  281. <transition event="exception" target=".">
  282. <parameter name="parameters"/>
  283. <raise scope="output" event="exception" port="action_out">
  284. <parameter expr="self.current_ID"/>
  285. <parameter expr="parameters"/>
  286. </raise>
  287. </transition>
  288. <transition port="input_in" event="input" target=".">
  289. <parameter name="value"/>
  290. <parameter name="context_ID"/>
  291. <script>
  292. self.inputs[context_ID].append(value)
  293. </script>
  294. </transition>
  295. </state>
  296. </state>
  297. </parallel>
  298. </scxml>
  299. </class>