modelverse.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. from sccd.runtime.statecharts_core import Event
  2. import sccd.runtime.socket2event as socket2event
  3. import modelverse_SCCD
  4. import time
  5. import threading
  6. # Exceptions
  7. class ModelverseException(Exception):
  8. pass
  9. class UnknownError(ModelverseException):
  10. pass
  11. class UnknownIdentifier(ModelverseException):
  12. pass
  13. class CompilationError(ModelverseException):
  14. pass
  15. class NoSuchAttribute(ModelverseException):
  16. pass
  17. class UnknownModel(ModelverseException):
  18. pass
  19. class ConnectionError(ModelverseException):
  20. pass
  21. class ModelExists(ModelverseException):
  22. pass
  23. class PermissionDenied(ModelverseException):
  24. pass
  25. class InvalidMode(ModelverseException):
  26. pass
  27. class InterfaceMismatch(ModelverseException):
  28. pass
  29. class UnknownMetamodellingHierarchy(ModelverseException):
  30. pass
  31. def run_controller():
  32. try:
  33. controller.start()
  34. finally:
  35. controller.stop()
  36. def _next_ID():
  37. global ID
  38. ID += 1
  39. return ID
  40. def INPUT(action, context, parameters):
  41. print("Executing " + str(action))
  42. print("Parameters: " + str(parameters))
  43. print("In context: " + str(context))
  44. controller.addInput(Event("action", "action_in", [action, _next_ID(), context, parameters]))
  45. def OUTPUT():
  46. while 1:
  47. response = responses.fetch(-1)
  48. print("Got response with name: " + str(response.name))
  49. if response.name == "result":
  50. print("Value: " + str(response.parameters[1]))
  51. return response.parameters[1]
  52. elif response.name == "exception":
  53. print("Exception: " + str(response.parameters))
  54. if response.parameters[1] == "UnknownIdentifier":
  55. raise UnknownIdentifier()
  56. elif response.parameters[1] == "UnknownMetamodellingHierarchy":
  57. raise UnknownMetamodellingHierarchy()
  58. def init(address_param="127.0.0.1:8001", timeout=20.0):
  59. global controller
  60. global ID
  61. global responses
  62. controller = modelverse_SCCD.Controller()
  63. socket2event.boot_translation_service(controller)
  64. ID = 0
  65. thrd = threading.Thread(target=run_controller)
  66. thrd.daemon = True
  67. thrd.start()
  68. responses = controller.addOutputListener("action_out")
  69. controller.addOutputListener("ready").fetch(-1)
  70. INPUT("init", None, [address_param, timeout])
  71. return OUTPUT()
  72. def login(username, password):
  73. INPUT("login", None, [username, password])
  74. return OUTPUT()
  75. def model_list(location):
  76. INPUT("model_list", None, [location])
  77. return OUTPUT()
  78. def model_add(model_name, metamodel_name, model_code=""):
  79. INPUT("model_add", None, [model_name, metamodel_name, model_code])
  80. return OUTPUT()
  81. def model_delete(model_name):
  82. INPUT("model_delete", None, [model_name])
  83. return OUTPUT()
  84. def model_list_full(location):
  85. INPUT("model_list_full", None, [location])
  86. return OUTPUT()
  87. def verify(model_name, metamodel_name):
  88. INPUT("verify", None, [model_name, metamodel_name])
  89. return OUTPUT()
  90. def model_overwrite(model_name, new_model, context=None):
  91. INPUT("model_overwrite", context, [model_name, new_model])
  92. return OUTPUT()
  93. def disconnect():
  94. INPUT("disconnect", None, [])
  95. return OUTPUT()
  96. def user_logout():
  97. INPUT("user_logout", None, [])
  98. return OUTPUT()
  99. def user_delete():
  100. INPUT("user_delete", None, [])
  101. return OUTPUT()
  102. def model_render(model_name, mapper_name):
  103. INPUT("model_render", None, [model_name, mapper_name])
  104. return OUTPUT()
  105. def transformation_between(source, target):
  106. INPUT("transformation_between", None, [source, target])
  107. return OUTPUT()
  108. def transformation_add_MT(source_metamodels, target_metamodels, operation_name, code, callback=None):
  109. INPUT("transformation_add_MT", None, [source_metamodels, target_metamodels, operation_name, code])
  110. context = OUTPUT()
  111. if callback is not None:
  112. callback(context)
  113. print("Callback finished; sending exit")
  114. INPUT("exit", context, [])
  115. return OUTPUT()
  116. def transformation_add_AL(source_metamodels, target_metamodels, operation_name, code, callback=None):
  117. INPUT("transformation_add_AL", None, [source_metamodels, target_metamodels, operation_name, code])
  118. context = OUTPUT()
  119. if callback is not None:
  120. callback(context)
  121. INPUT("exit", context, [])
  122. return OUTPUT()
  123. def transformation_add_MANUAL(source_metamodels, target_metamodels, operation_name, callback=None):
  124. INPUT("transformation_add_MANUAL", None, [source_metamodels, target_metamodels, operation_name])
  125. context = OUTPUT()
  126. if callback is not None:
  127. print("DOING CALLBACK FOR MANUAL")
  128. callback(context)
  129. print("CALLBACK FINISHED")
  130. INPUT("exit", context, [])
  131. return OUTPUT()
  132. def transformation_execute_MT(operation_name, input_models_dict, output_models_dict, statechart=None):
  133. if statechart is not None:
  134. port_sc = statechart[0].addOutputListener(statechart[2])
  135. INPUT("transformation_execute_MT", None, [operation_name, input_models_dict, output_models_dict])
  136. context = OUTPUT()
  137. if statechart is not None:
  138. while 1:
  139. empty = True
  140. # Fetch output from the MV
  141. response = responses.fetch(0)
  142. if response is not None:
  143. print("Got response from MV: " + str(response))
  144. if response.name == "data_output":
  145. # Got output of MV, so forward to SCCD
  146. statechart[0].addInput(Event("input", statechart[1], response.parameters))
  147. elif response.name == "result":
  148. # Finished execution, so continue and return result
  149. statechart[0].addInput(Event("terminate", statechart[1], []))
  150. return response.parameters[1]
  151. empty = False
  152. # Fetch output from the SC
  153. response = port_sc.fetch(0)
  154. if response is not None:
  155. print("Got response from SC: " + str(response))
  156. if response.name == "output":
  157. controller.addInput(Event("data_input", "action_in", [response.parameters, context]))
  158. empty = False
  159. if empty:
  160. time.sleep(0.01)
  161. else:
  162. return OUTPUT()
  163. def transformation_execute_AL(operation_name, input_models_dict, output_models_dict, statechart=None):
  164. if statechart is not None:
  165. port_sc = statechart[0].addOutputListener(statechart[2])
  166. INPUT("transformation_execute_AL", None, [operation_name, input_models_dict, output_models_dict])
  167. context = OUTPUT()
  168. if statechart is not None:
  169. while 1:
  170. empty = True
  171. # Fetch output from the MV
  172. response = responses.fetch(0)
  173. if response is not None:
  174. print("Got response from MV: " + str(response))
  175. if response.name == "data_output":
  176. # Got output of MV, so forward to SCCD
  177. statechart[0].addInput(Event("input", statechart[1], response.parameters))
  178. elif response.name == "result":
  179. # Finished execution, so continue and return result
  180. statechart[0].addInput(Event("terminate", statechart[1], []))
  181. return response.parameters[1]
  182. empty = False
  183. # Fetch output from the SC
  184. response = port_sc.fetch(0)
  185. if response is not None:
  186. print("Got response from SC: " + str(response))
  187. if response.name == "output":
  188. controller.addInput(Event("data_input", "action_in", [response.parameters, context]))
  189. empty = False
  190. if empty:
  191. time.sleep(0.01)
  192. else:
  193. return OUTPUT()
  194. def transformation_execute_MANUAL(operation_name, input_models_dict, output_models_dict, callback=None):
  195. INPUT("transformation_execute_MANUAL", None, [operation_name, input_models_dict, output_models_dict])
  196. context = OUTPUT()
  197. if callback is not None:
  198. callback(context)
  199. INPUT("exit", context, [])
  200. return OUTPUT()
  201. def permission_modify(model_name, permissions):
  202. INPUT("permission_modify", None, [model_name, permissions])
  203. return OUTPUT()
  204. def permission_owner(model_name, permission):
  205. INPUT("permission_owner", None, [model_name, permission])
  206. return OUTPUT()
  207. def permission_group(model_name, group):
  208. INPUT("permission_group", None, [model_name, group])
  209. return OUTPUT()
  210. def group_create(group_name):
  211. INPUT("group_create", None, [group_name])
  212. return OUTPUT()
  213. def group_delete(group_name):
  214. INPUT("group_delete", None, [group_name])
  215. return OUTPUT()
  216. def group_owner_add(group_name, user_name):
  217. INPUT("group_owner_add", None, [group_name, user_name])
  218. return OUTPUT()
  219. def group_owner_delete(group_name, user_name):
  220. INPUT("group_owner_delete", None, [group_name, user_name])
  221. return OUTPUT()
  222. def group_join(group_name, user_name):
  223. INPUT("group_join", None, [group_name, user_name])
  224. return OUTPUT()
  225. def group_kick(group_name, user_name):
  226. INPUT("group_kick", None, [group_name, user_name])
  227. return OUTPUT()
  228. def group_list():
  229. INPUT("group_list", None, [])
  230. return OUTPUT()
  231. def admin_promote(user_name):
  232. INPUT("admin_promote", None, [user_name])
  233. return OUTPUT()
  234. def admin_demote(user_name):
  235. INPUT("admin_demote", None, [user_name])
  236. return OUTPUT()
  237. def conformance_delete(model_name, metamodel_name):
  238. INPUT("conformance_delete", None, [model_name, metamodel_name])
  239. return OUTPUT()
  240. def conformance_add(model_name, metamodel_name):
  241. INPUT("conformance_add", None, [model_name, metamodel_name])
  242. return OUTPUT()
  243. def folder_create(folder_name):
  244. INPUT("folder_create", None, [folder_name])
  245. return OUTPUT()
  246. def model_types(model_name):
  247. INPUT("model_types", None, [model_name])
  248. return OUTPUT()
  249. def alter_context(model_name, metamodel_name):
  250. INPUT("alter_context", None, [model_name, metamodel_name])
  251. return OUTPUT()
  252. def element_list(model_name, context=None):
  253. INPUT("element_list", context, [model_name])
  254. return OUTPUT()
  255. def element_list_nice(model_name, context=None):
  256. INPUT("element_list_nice", context, [model_name])
  257. return OUTPUT()
  258. def types(model_name, context=None):
  259. INPUT("types", context, [model_name])
  260. return OUTPUT()
  261. def types_full(model_name, context=None):
  262. INPUT("types_full", context, [model_name])
  263. return OUTPUT()
  264. def read_info(model_name, ID, context=None):
  265. INPUT("read_info", context, [model_name, ID])
  266. return OUTPUT()
  267. def read_attrs(model_name, ID, context=None):
  268. INPUT("read_attrs", context, [model_name, ID])
  269. return OUTPUT()
  270. def instantiate(model_name, typename, edge=None, ID="", context=None):
  271. INPUT("instantiate", context, [model_name, typename, edge, ID])
  272. return OUTPUT()
  273. def delete_element(model_name, ID, context=None):
  274. INPUT("delete_element", context, [model_name, ID])
  275. return OUTPUT()
  276. def attr_assign(model_name, ID, attr, value, context=None):
  277. INPUT("attr_assign", context, [model_name, ID, attr, value])
  278. return OUTPUT()
  279. def attr_assign_code(model_name, ID, attr, code, context=None):
  280. INPUT("attr_assign_code", context, [model_name, ID, attr, code])
  281. return OUTPUT()
  282. def attr_delete(model_name, ID, attr, context=None):
  283. INPUT("attr_delete", context, [model_name, ID, attr])
  284. return OUTPUT()
  285. def read_outgoing(model_name, ID, typename, context=None):
  286. INPUT("read_outgoing", context, [model_name, ID, typename])
  287. return OUTPUT()
  288. def read_incoming(model_name, ID, typename, context=None):
  289. INPUT("read_incoming", context, [model_name, ID, typename])
  290. return OUTPUT()
  291. def read_association_source(model_name, ID, context=None):
  292. INPUT("read_association_source", context, [model_name, ID])
  293. return OUTPUT()
  294. def read_association_destination(model_name, ID, context=None):
  295. INPUT("read_association_destination", context, [model_name, ID])
  296. return OUTPUT()
  297. def connections_between(model_name, source, target, context=None):
  298. INPUT("connections_between", context, [model_name, source, target])
  299. return OUTPUT()
  300. def define_attribute(model_name, node, attr_name, attr_type, context=None):
  301. INPUT("define_attribute", context, [model_name, node, attr_name, attr_type])
  302. return OUTPUT()
  303. def all_instances(model_name, type_name, context=None):
  304. INPUT("all_instances", context, [model_name, type_name])
  305. return OUTPUT()
  306. def process_execute(process_name, prefix, callbacks=None):
  307. # for all callbacks to SCs, start up the output port already
  308. sc_ports = {}
  309. for k, v in callbacks.items():
  310. if isinstance(v, (tuple, list)):
  311. # Is a statechart, so register already
  312. sc_ports[k] = v[0].addOutputListener(v[2])
  313. INPUT("process_execute", None, [process_name, prefix])
  314. operation = OUTPUT()
  315. while 1:
  316. print("Operation: " + str(operation))
  317. if isinstance(operation, (list, tuple)):
  318. t, name, context = operation
  319. print("Executing operation of type %s with name %s in context %s" % (t, name, context))
  320. if t == "OP":
  321. if name in callbacks:
  322. callbacks[name](context)
  323. INPUT("exit", context, [])
  324. operation = OUTPUT()
  325. elif t == "SC":
  326. if name in callbacks:
  327. statechart = callbacks[name]
  328. else:
  329. statechart = None
  330. while 1:
  331. empty = True
  332. # Fetch output from the MV
  333. response = responses.fetch(0)
  334. if response is not None:
  335. print("Got response from MV: " + str(response))
  336. if response.name == "data_output":
  337. # Got output of MV, so forward to SCCD
  338. if statechart:
  339. statechart[0].addInput(Event("input", statechart[1], response.parameters))
  340. elif response.name == "result":
  341. # Finished execution, so continue and return result
  342. if statechart:
  343. statechart[0].addInput(Event("terminate", statechart[1], []))
  344. # Break from the most inner loop
  345. operation = response.parameters[1]
  346. break
  347. empty = False
  348. # Fetch output from the SC
  349. if statechart:
  350. response = sc_ports[name].fetch(0)
  351. if response is not None:
  352. print("Got response from SC: " + str(response))
  353. if response.name == "output":
  354. controller.addInput(Event("data_input", "action_in", [response.parameters, context]))
  355. empty = False
  356. if empty:
  357. time.sleep(0.01)
  358. else:
  359. if operation == "Finished":
  360. # Finished execution of the process, so exit
  361. return None
  362. # TODO monitor the new function and execute the correct callback