wrappers.rst 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. Wrappers
  2. ========
  3. Several wrappers can be defined for the Modelverse, as the Modelverse is merely a service running externally.
  4. To communicate effectively, and automatically, a programming language wrapper is recommended.
  5. Nonetheless, it is possible to communicatie manually as well.
  6. These are some of the implemented wrappers.
  7. Prompt
  8. ------
  9. The simplest wrapper is the prompt wrapper, which merely sends the input and output directly to the user.
  10. This wrapper has almost no code, but requires users to manually decide which content to send next.
  11. It has no built-in integration with any model or action language compilers.
  12. Nonetheless, it is an easy way to test out the raw communication protocol manually.
  13. Python
  14. ------
  15. The first real wrapper is the Python-based wrapper.
  16. It provides a set of functions for use by Python code.
  17. These functions wrap not only the interface, but also provides simple error handling through the use of Python exceptions and contains the model and action language compilers.
  18. An overview of all functions and associatied exceptions is provided below.
  19. All operations happen *synchronously*, meaning that they block until the Modelverse has performed the requested operation.
  20. Note that some functions are only applicable in a certain *context*.
  21. In practice, this means that you should first issue the *init* and *login* operations, as otherwise your connection with the Modelverse will not have started up yet.
  22. For each function, we provide an example to indicate how this operation can be used.
  23. In these first examples, assume that all referenced elements are present, all permissions are granted, etc.
  24. For each exception, then, we provide an example where it can occur.
  25. In these examples, the problem is often caused by an non-existing element or unsatisfied permissions.
  26. From the example, it should be clear what the problem is.
  27. Functions
  28. ^^^^^^^^^
  29. .. function:: init(address_param="http://127.0.0.1:8001", timeout=20.0)
  30. Start up the connection to the Modelverse, residing at *address_param*.
  31. This connection is an XML/HTTPRequest and will start up a new task at the Modelverse.
  32. Retries for *timeout* seconds until giving up.
  33. The timeout includes all HTTP errors, and will therefore keep retrying even on failed attempts.
  34. As this request is synchronous, like all others, it will block until a connection has been established.
  35. Examples:
  36. To create a connection to the Modelverse that runs locally at port 8001 (default configuration):
  37. .. code::
  38. >> init()
  39. To create a connection to the Modelverse running remotely:
  40. .. code::
  41. >> init("http://modelverse.uantwerpen.be:8001")
  42. .. function:: login(username, password)
  43. Explanation
  44. Logs in the currently active Modelverse connection to the specified *username* and *password*.
  45. If the user does not exist, it will create a new user with the specified password.
  46. If the user already exists, it will try to log in with the provided password.
  47. Examples:
  48. To login as user user1, with the specified password:
  49. .. code::
  50. >> login("user1", "my_password")
  51. .. function:: model_add(model_name, metamodel_name, model_code=None)
  52. Explanation
  53. Upload a new model that can later be referred to as *model_name*, conforming to *metamodel_name*.
  54. The model itself is stored in the string *model_code*.
  55. This string is parsed using the HUTN compiler and subsequently sent to the Modelverse.
  56. When *model_code* is empty, an empty model is created.
  57. Examples:
  58. To create a new model called PetriNets, conforming to SimpleClassDiagrams, and load the model stored in models/PetriNets.mvc:
  59. .. code::
  60. >> model_add("PetriNets", "SimpleClassDiagrams", open("models/PetriNets.mvc", "r").read())
  61. To create a minimal instance of the language afterwards, which only contains a single place (and no attributes):
  62. .. code::
  63. >> model_add("my_pn", "PetriNets", """Place p1 {}""")
  64. To create a less minimal instance of the language, stored in models/my_pn2.mvc:
  65. .. code::
  66. >> model_add("my_pn2", "PetriNets", open("models/my_pn2.mvc", "r").read())
  67. .. function:: upload_code(code)
  68. Upload a string of *code* in the Action Language formalism.
  69. This piece of code is compiled with the HUTN compiler and sent to the Modelverse directly.
  70. Makes the assumption that the **construct_function()** operation is currently running on the Modelverse, as otherwise the data will be misinterpreted.
  71. This is normally only useful in model transformations, where you want to upload a piece of code on-the-fly (e.g., adding a breakpoint in Action Language).
  72. Examples:
  73. To upload the file models/code.alc:
  74. .. code::
  75. >> upload_code(open("models/code.alc", "r").read())
  76. To upload a code fragment inline:
  77. .. code::
  78. >> upload_code("Void function a():\nreturn!")
  79. .. function:: model_delete(model_name)
  80. Delete the model referred to by name *model_name*.
  81. This is a non-cascading delete, with almost no checks: model transformations depending on this model will likely become corrupted.
  82. Examples:
  83. To delete a previously created model:
  84. .. code::
  85. >> model_delete("my_pn2")
  86. Or to delete a metamodel, which is itself just a model:
  87. .. code::
  88. >> model_delete("PetriNets")
  89. .. function:: model_list()
  90. Returns a list of all models existing in the Modelverse, together with their type.
  91. Examples:
  92. .. code::
  93. >> model_list()
  94. [("my_pn", "PetriNets"),
  95. ("my_pn2", "PetriNets"),
  96. ("PetriNets", "SimpleClassDiagrams"),
  97. ("SimpleClassDiagrams", "SimpleClassDiagrams")]
  98. .. function:: model_list_full()
  99. Returns a detailed list of all models existing in the Modelverse.
  100. This list includes information on permissions, owner, and group.
  101. Examples:
  102. .. code::
  103. >> model_list_full()
  104. [("my_pn", "PetriNets", "user1", "users", "200"),
  105. ("my_pn2", "PetriNets", "user1", "users", "200"),
  106. ("PetriNets", "SimpleClassDiagrams", "user1", "users", "211"),
  107. ("SimpleClassDiagrams", "SimpleClassDiagrams", "admin", "admin", "211")]
  108. .. function:: verify(model_name)
  109. Verify whether *model_name* conforms to its specified metamodel, as stored in the Modelverse.
  110. Returns either "OK" if the model conforms, or a string specifying the reason for non-conformance.
  111. Examples:
  112. When verifying a conforming model:
  113. .. code::
  114. >> verify("PetriNets")
  115. OK
  116. When verifying a non-conforming model:
  117. .. code::
  118. >> verify("my_pn")
  119. Lower cardinality violation for attribute "name" at Place p1.
  120. .. function:: model_overwrite(model_name, new_model_code=None)
  121. Overwrites the model previously known under the name *model_name* with the model code in *new_model_code*.
  122. This operation differs from first deleting the model and then recreating it, as all metadata of the model is kept, such as access permissions.
  123. The new model can be kept empty, in which case the model will be cleared.
  124. Examples:
  125. To overwrite the PetriNets metamodel with a newer version, thereby also updating the metamodel of all existing instances ("my_pn" and "my_pn2"):
  126. .. code::
  127. >> model_overwrite("PetriNets", open("models/PetriNets2.mvc", "r").read())
  128. To overwrite an existing PetriNets instance:
  129. .. code::
  130. >> model_overwrite("my_pn", """Place p2 {}""")
  131. .. function:: user_logout()
  132. Logs out the current user, thereby closing the task.
  133. Subsequent operations will no longer have any effect, as the task was terminated.
  134. To log in as a different user, the *init* operation has to be executed again.
  135. Examples:
  136. To log out the current user and allow future logins by this user:
  137. .. code::
  138. >> user_logout()
  139. .. function:: user_delete()
  140. Delete the current user and thereafter log out.
  141. This removes the current user, making it impossible to log in as this user again.
  142. Existing models tied to this user, such as those the user is an owner of, remain bound to the (removed) user.
  143. While it is possible to recreate a new user with the same name, model permissions will not be inherited to this new user with the same name.
  144. Examples:
  145. To delete the current user, and make all owned models owner-less:
  146. .. code::
  147. >> user_delete()
  148. .. function:: model_render(model_name, mapper_name)
  149. Render the model by name of *model_name* using the mapper by name of *mapper_name*.
  150. Both parameters have to be known models in the Modelverse.
  151. Outputs a JSON representation of the rendered model.
  152. This is basically just a shortcut for executing the specified operation and reading out the resulting model with a JSON representation.
  153. Examples:
  154. To render the PetriNets instance using the PetriNetsMapper:
  155. .. code::
  156. >> model_render("my_pn", "PetriNetsMapper")
  157. [{"id": "__12345", "type": "Ellipse", "x": 100, "y": 150, "height": 20, "width: "20"}]
  158. .. function:: transformation_between(source, target)
  159. List all transformations that originate at *source* and end at *target*.
  160. Transformations can still be selected, even if they take more source models than those specified in the parameters.
  161. Examples:
  162. To fetch all endogenous transformations on PetriNets, assuming that some were previously defined:
  163. .. code::
  164. >> transformation_between("PetriNets", "PetriNets")
  165. ["PN_simulate", "PN_optimize"]
  166. To fetch all transformations from a DSL to PetriNets, assuming that multiple people created different denotational semantics:
  167. .. code::
  168. >> transformation_between("RPGame", "PetriNets")
  169. ["denotational1", "denotational_2", "denotational_3"]
  170. .. function:: transformation_add_MT(source_metamodels, target_metamodels, operation_name, code, callback=lambda: None)
  171. Create a new model transformation operation.
  172. The new transformation takes *source_metamodels* as input, and generates *target_metamodels* as output.
  173. Both parameters are dictionaries of the form {name: metamodel_name}.
  174. The name is used later on in the model transformation as a prefix to the type.
  175. A single metamodel_name can be used for multiple names.
  176. Note that the target metamodel names may overlap with the source metamodel names, but the metamodel type should be identical.
  177. The operation is henceforth known by *operation_name* and is provided as a model in the string *code*.
  178. Optionally, a callback is defined which performs some operations on the merged metamodel, for example to define tracability links between (previously unrelated) metamodels.
  179. In the background, this operation does all necessary RAMification and model merging.
  180. Examples:
  181. To create a new model transformation for PetriNets simulation:
  182. .. code::
  183. >> transformation_add_MT({"pn": "PetriNets"}, {"pn": "PetriNets"}, "pn_simulate", open("models/PN_simulate.mvc", "r").read())
  184. To create a model transformation from a DSL to PetriNets, which requires tracability links:
  185. .. code::
  186. >> def tracability_links():
  187. >> instantiate("Association", ID="Tile2Place", ("dsl/Tile", "pn/Place"))
  188. >> instantiate("Association", ID="Dirrection2Transition", ("dsl/Direction", "pn/Transition"))
  189. >> transformation_add_MT({"dsl": "RPGame"}, {"pn": "PetriNets"}, "denotational_1", open("models/denotational_1.mvc", "r").read(), tracability_links)
  190. To create a multi-input model transformation:
  191. .. code::
  192. >> transformation_add_MT({"pn_1": "PetriNets", "pn_2": "PetriNets", "architecture: "Architecture"}, {"result": "PetriNets"}, "PN_merge", open("models/PN_merge.mvc", "r").read())
  193. .. function:: transformation_add_AL(source_metamodels, target_metamodels, operation_name, code, callback=lambda: None)
  194. Creates a new action language operation.
  195. Similar to *transformation_add_MT*, but now does not require RAMification.
  196. The *code* parameter also is not specified as a Modelverse model (.mvc), but as action language (.alc).
  197. Examples:
  198. To create a new action language operation for PetriNets reachability analysis:
  199. .. code::
  200. >> transformation_add_AL({"pn": "PetriNets"}, {"graph": "ReachabilityGraph"}, "pn_analyze", open("models/PN_reachability.alc", "r").read())
  201. To create an action language operation from a Scheduling DSL to a list, which requires tracability links:
  202. .. code::
  203. >> def tracability_links():
  204. >> instantiate("Association", ID="Task2Event", ("schedule/Task", "list/Event"))
  205. >> transformation_add_AL({"schedule": "SchedulingDSL"}, {"list": "EventList"}, "sequentialize", open("models/sequentialize_schedule.alc", "r").read(), tracability_links)
  206. .. function:: transformation_add_MANUAL(source_metamodels, target_metamodels, operation_name, callback=lambda: None)
  207. Creates a new manual operation.
  208. Identical to *transformation_add_AL*, but does not take any code as content.
  209. Examples:
  210. To create a manual refinement operation on PetriNets:
  211. .. code::
  212. >> transformation_add_MANUAL({"pn": "PetriNets"}, {"pn": "PetriNets"}, "pn_refine")
  213. To create a multi-input refinement operation on PetriNets:
  214. .. code::
  215. >> transformation_add_MANUAL({"pn": "PetriNets", "requirements": "Requirements"}, {"pn": "PetriNets"}, "pn_refine_req")
  216. .. function:: transformation_execute_AL(operation_name, input_models_dict, output_models_dict, callback=lambda i: None)
  217. Executes the Action Language model *operation_name* with *input_models_dict* as inputs and *output_models_dict* as outputs.
  218. For both dicts, the contents describe the mapping between the parameter names of the operation to the names in the Modelverse.
  219. Values in *input_models_dict* must be existing models, whereas values in *output_models_dict* can be non-existing upon invocation.
  220. A *callback* function can be defined when the action language model requires user input or output.
  221. This callback function can be used to communicate with the executing action language directly.
  222. Examples:
  223. To execute reachability analysis on an existing petri net:
  224. .. code::
  225. >> transformation_execute_AL("pn_analyze", {"pn": "my_pn"}, {"graph": "my_pn_reachability"})
  226. To execute reachability analysis which prompts the user, for example because it is a debugging prompt:
  227. .. code::
  228. >> def callback(value):
  229. >> print(value)
  230. >> return raw_input()
  231. >> transformation_execute_AL("pn_simulate", {"pn": "my_pn"}, {"graph": "my_pn_reachability"}, callback)
  232. << Which operation do you want to execute?
  233. >> step
  234. << Step performed! New operation?
  235. >> continuous
  236. << Finished analysis!
  237. .. function:: transformation_execute_MANUAL(operation_name, input_models_dict, output_models_dict, callback=lambda i: None)
  238. Executes the manual model operation *operation_name*.
  239. Furthermore, this is identical to *transformation_execute_AL*, with the exception of the *callback* function.
  240. In this case, the callback function can be just another series of Modelverse operations, though pertaining to a single model.
  241. As such, the *model_name* parameter of these operations **MUST** be set to *None*.
  242. Examples:
  243. To execute a manual operation, which requires you to refine a PetriNets instance:
  244. .. code::
  245. >> def callback():
  246. >> p1 = instantiate(None, "pn/Place")
  247. >> t1 = instantiate(None, "pn/Transition")
  248. >> instantiate(None, "pn/P2T", (p1, t1))
  249. >> transformation_execute_MANUAL("pn_refine", {"pn": "my_pn"}, {"pn": "my_pn"}, callback)
  250. .. function:: transformation_execute_MT(operation_name, input_models_dict, output_models_dict, callback=lambda i: None)
  251. Executes the model transformation operation *operation_name*.
  252. Identical to *transformation_execute_AL*.
  253. Examples:
  254. To execute a model transformation on a PetriNets instance, thereby putting the result in a different model:
  255. .. code::
  256. >> transformation_execute_MT("pn_simulate", {"pn": "my_pn"}, {"pn": "my_simulated_pn"})
  257. To execute a model transformation which prompts the user:
  258. .. code::
  259. >> def callback(value):
  260. >> print(value)
  261. >> return raw_input()
  262. >> transformation_execute_MT("pn_simulate_prompt", {"pn": "my_pn"}, {"pn": "my_simulated_pn"}, callback)
  263. .. function:: transformation_list()
  264. Returns a list of all operations specified in the Modelverse, together with their type.
  265. Examples:
  266. To fetch a list of all transformations and their type of operation:
  267. .. code::
  268. >> transformation_list()
  269. [("pn_simulate", "ModelTransformation"),
  270. ("pn_reachability", "ActionLanguage"),
  271. ("pn_simulate_prompt", "ModelTransformation"),
  272. ("pn_refine", "ManualOperation")]
  273. .. function:: process_execute(process_name, prefix, callbacks)
  274. Execute the process model stored as *process_name*.
  275. All models are stored with their names prefixed with *prefix* to allow for multiple executions of the same model.
  276. Note that this applies to the resolution of input models as well.
  277. Optionally, a dictionary of *callbacks* can be defined with as key the operation that is being executed, and value the actual callback.
  278. The callbacks must be similarly defined just like how they were defined in the individual *transformation_execute* operations.
  279. Examples:
  280. To execute a process model for the power window example:
  281. .. code::
  282. >> process_execute("pm_powerwindow", "pw_")
  283. To execute a process model for the power window example, which requires user input for some operations:
  284. .. code::
  285. >> def refine_architecture():
  286. >> # Do some operation on the architecture model here
  287. >> node1 = instantiate(None, "Node")
  288. >> node2 = instantiate(None, "Node")
  289. >> instantiate(None, "Connection", (node1, node2))
  290. >> def refine_control():
  291. >> # Do some operation on the control model here
  292. >> s1 = instantiate(None, "State")
  293. >> s2 = instantiate(None, "State")
  294. >> instantiate(None, "Transition", (s1, s2))
  295. >> def refine_query():
  296. >> # Do some operation on the safety query model here
  297. >> p1 = instantiate(None, "Place")
  298. >> attr_assign(None, p1, "tokens", 2)
  299. >> process_execute("pm_powerwindow", "pw_", {"refine_plant": refine_plant, "refine_control": refine_control, "refine_query": refine_query})
  300. .. function:: permission_modify(model_name, permissions)
  301. Change the permissions of *model_name* to *permissions*.
  302. The permissions is a string of three characters, each between 0 and 2.
  303. The format is similar to the UNIX permission system: the leftmost character is the permission for the owning user, the middle character for members of the ownin group, and the rightmost character for all other users.
  304. Character 0 signifies no access, 1 read-only access, and 2 full read/write access.
  305. Note that changing permissions trickle down to the instances as well: if the metamodel is no longer readable to the user, all models conforming to it become unreadable in this specific context.
  306. Examples:
  307. To modify the permissions of the PetriNets metamodel, allowing only the owner to read and write to it:
  308. .. code::
  309. >> permission_modify("PetriNets", "200")
  310. To modify the permissions of a PetriNets model, granting everyone read/write access:
  311. .. code::
  312. >> permission_modify("PetriNets", "222")
  313. .. function:: permission_owner(model_name, owner)
  314. Change the owner of the model *model_name* to *owner*.
  315. Changing permissions trickles down to the instances as well: if the metamodel is no longer readable to the user, all models conforming to it become unreadable in this specific context.
  316. Examples:
  317. To change the owning user of the PetriNets metamodel to user2:
  318. .. code::
  319. >> permission_owner("PetriNets", "user2")
  320. .. function:: permission_group(model_name, group)
  321. Change the owning group of the model *model_name* to *group*.
  322. The same remarks hold as for all other permission operations.
  323. Examples:
  324. To change the owning group of the PetriNets metamodel to group1:
  325. .. code::
  326. >> permission_group("PetriNets", "group1")
  327. .. function:: group_create(group_name)
  328. Create a new group named *group_name*.
  329. You automatically become an administrator for this group.
  330. Examples:
  331. To create a new group called group2:
  332. .. code::
  333. >> group_create("group2")
  334. .. function:: group_delete(group_name)
  335. Delete the group named *group_name*.
  336. All users will automatically be kicked from the group, and all permissions previously granted by this group become void.
  337. Examples:
  338. To delete the group group2
  339. .. code::
  340. >> group_delete("group2")
  341. .. function:: group_owner_add(group_name, user_name)
  342. Add user *user_name* as an owner of group *group_name*.
  343. This automatically makes the user join the specified group if this was not yet the case.
  344. Examples:
  345. To add user user1 as a new owner, or group administrator, to group group1:
  346. .. code::
  347. >> group_owner_add("group1", "user1")
  348. .. function:: group_owner_delete(group_name, user_name)
  349. Remove user *user_name* as an owner of group *group_name*.
  350. Examples:
  351. To delete user1 as an owner, or group administrator, from group group1:
  352. .. code::
  353. >> group_owner_delete("group1", "user1")
  354. .. function:: group_join(group_name, user_name)
  355. Have user *user_name* join the group *group_name* as an ordinary user.
  356. Examples:
  357. To make user user1 join the group group1, of which the current user is an owner:
  358. .. code::
  359. >> group_join("group1", "user1")
  360. .. function:: group_kick(group_name, user_name)
  361. Remove user *user_name* from the group *group_name*.
  362. If the user was an owner of the group, these permissions are also revoked.
  363. Examples:
  364. To kick user user1 from group group1, of which the current user is an owner:
  365. .. code::
  366. >> group_kick("group1, "user1")
  367. .. function:: admin_promote(user_name)
  368. Promote user *user_name* to admin status.
  369. Admin status grants users access to all operations, and provides all permission.
  370. Effectively, all groups and files have read/write access for the admin user, independent of the stored permissions.
  371. Examples:
  372. To promote user1 to admin states:
  373. .. code::
  374. >> admin_promote("user1")
  375. .. function:: admin_demote(user_name)
  376. Demote user *user_name* to ordinary user.
  377. Examples:
  378. To demote user1 to a normal user:
  379. .. code::
  380. >> admin_demote("user1")
  381. .. function:: element_list(model_name)
  382. Returns a list of all elements and their type specified in the model named *model_name*.
  383. This list can contain much more than only simple elements, but includes anonymous edges and attributes as well.
  384. It is therefore not recommended for general purpose use; use *element_list_nice* instead.
  385. Examples:
  386. To get a list of all elements in the PetriNets metamodel:
  387. .. code::
  388. >> element_list("PetriNets")
  389. [("Place", "Class"),
  390. ("Transition", "Class"),
  391. ("P2T", "Association"),
  392. ("T2P", "Association"),
  393. ...]
  394. .. function:: types(model_name)
  395. Returns a list of all types usable in the model named *model_name*.
  396. This is similar to executing *element_list* on the metamodel of this model.
  397. It attempts to filter out most unusable elements.
  398. Examples:
  399. To get a list of all types usable in the PetriNets metamodel (i.e., when altering the metamodel itself):
  400. .. code::
  401. >> types("PetriNets")
  402. ["Class", "Association", "SimpleAttribute", ...]
  403. .. function:: types_full(model_name)
  404. Returns a list of all types usable in the model named *model_name*.
  405. In contrast to *types*, this includes hidden elements as well (i.e., those starting with __)
  406. Examples:
  407. To get a list of all types usable in the PetriNets metamodel (i.e., when altering the metamodel itself):
  408. .. code::
  409. >> types("PetriNets")
  410. ["Class", "Association", "SimpleAttribute", "__12345", ...]
  411. .. function:: read(model_name, ID)
  412. Read the content of model element *ID* in model *model_name*.
  413. This returns the type of the element, and the set of source and destination if the element is an edge (*None* otherwise).
  414. Examples:
  415. To read out the P2T link in the PetriNets metamodel:
  416. .. code::
  417. >> read("PetriNets", "P2T")
  418. ["Association", ("Place", "Transition")]
  419. To read out the Place node in the PetriNets metamodel:
  420. .. code::
  421. >> read("PetriNets", "Place")
  422. ["Class", None]
  423. To read out some P2T instance in a PetriNets model:
  424. .. code::
  425. >> read("my_pn", "p1_to_t1")
  426. ["P2T", ("p1", "t1")]
  427. To read out some Place instance in a PetriNets model:
  428. .. code::
  429. >> read("my_pn", "p1")
  430. ["Place", None]
  431. .. function:: read_attrs(model_name, ID)
  432. Return a dictionary of all attributes of model element *ID* in model *model_name*, containing their values.
  433. All values in the Modelverse are primitive types, and as such, this is also the case in this operation.
  434. The value is *None* in case the attribute is not set.
  435. Examples:
  436. To read out the attributes of the Place class:
  437. .. code::
  438. >> read_attrs("PetriNets", "Place")
  439. {"lower_cardinality": None, "upper_cardinality": None}
  440. To read out the attributes of a Place instance:
  441. .. code::
  442. >> read_attrs("my_pn", "p1")
  443. {"name": "critical_section", "tokens": 1}
  444. .. function:: instantiate(model_name, typename, edge=None, ID="")
  445. Instantiate a new instance of *typename* in the model *model_name*.
  446. If the instance is an edge, provide a tuple containing the source and target as *edge*.
  447. A preferred *ID* can be specified, though there is no guarantee that this name is actually used (e.g., if it is already taken by another element).
  448. This operation returns the actually assigned ID.
  449. It is this ID that is used for all other operations on the model.
  450. Examples:
  451. To create a new Place instance in a PetriNets model:
  452. .. code::
  453. >> instantiate("my_pn", "Place")
  454. "__12345"
  455. To create a new Place instance with a preferred ID, which is granted:
  456. .. code::
  457. >> instantiate("my_pn", "Place", ID="critical_section")
  458. "critical_section"
  459. To create a new Place instance with a preferred ID, which is not granted:
  460. .. code::
  461. >> instantiate("my_pn", "Place", ID="critical_section")
  462. "critical_section_12345"
  463. To create a new P2T instance in a PetriNets model:
  464. .. code::
  465. >> instantiate("my_pn", "P2T", ("p1", "t1"))
  466. "__12345"
  467. To create a new concept in the PetriNets metamodel, which can later on be used:
  468. .. code::
  469. >> instantiate("PetriNets", "Association", ("Place", "Transition"), ID="InhibitorArc")
  470. "InhibitorArc"
  471. >> instantiate("my_pn", "InhibitorArc", ("p1", "t1"))
  472. "__12345"
  473. .. function:: delete_element(model_name, ID)
  474. Delete the element *ID* in the model *model_name*.
  475. This is a recursive delete, and all incoming and outgoing edges will be removed (recursively) as well.
  476. Examples:
  477. To delete an existing element in a PetriNets model:
  478. .. code::
  479. >> delete_element("my_pn", "critical_section")
  480. To delete an existing exdge in a PetriNets model:
  481. .. code::
  482. >> delete_element("my_pn", "p1_to_t1")
  483. When deleting an element "p1", the arc "p1_to_t1" is also removed automatically.
  484. .. code::
  485. >> delete_element("my_pn", "p1")
  486. >> delete_element("my_pn", "p1_to_t1") # <-- Raises an exception: arc is already removed
  487. .. function:: attr_assign(model_name, ID, attr, value)
  488. Assign the value *value* to the attribute named *attr* of the element *ID* in the model named *model_name*.
  489. If the attribute already has an assigned value, the previous value is removed first.
  490. Examples:
  491. To assign some attributes to a Place instance:
  492. .. code::
  493. >> attr_assign("my_pn", "p1", "name", "my first place")
  494. >> attr_assign("my_pn", "p1", "tokens", 1)
  495. To assign some attributes to the Place class itself:
  496. .. code::
  497. >> attr_assign("PetriNets", "Place", "upper_cardinality", 1)
  498. .. function:: attr_assign_code(model_name, ID, attr, code)
  499. Assign the code block *code* to the attribute named *attr* of the element *ID* in the model named *model_name*.
  500. If the attribute already has an assigned value, the previous value is removed first.
  501. The assigned code is compiled to Action Language by the HUTN compiler.
  502. Examples:
  503. To assign a piece of action code to a Statecharts transition, loaded from file:
  504. .. code::
  505. >> attr_assign_code("my_sc", "t1", "script", open("models/t1_script", "r").read())
  506. To assign a piece of action code to a Statecharts transition, defined inline
  507. .. code::
  508. >> code = \
  509. >> """
  510. >> Void function action(attributes : Element):
  511. >> dict_overwrite(attributes, "counter", 1)
  512. >> return!
  513. >> """
  514. >> attr_assign_code("my_sc", "t1", "script", code)
  515. .. function:: attr_delete(model_name, ID, attr)
  516. Unset the attribute *attr* of model element *ID* in the model *model_name*.
  517. This is not necessary when assigning a new value, as *attr_assign* automatically does this when required.
  518. As such, this only is useful when dealing with an optional attribute, or when you want to create a non-conforming model.
  519. Examples:
  520. To unset the name attribute of a place
  521. .. code::
  522. >> attr_delete("my_pn", "p1", "name")
  523. .. function:: read_outgoing(model_name, ID, typename)
  524. Returns a list of all outgoing associations of *ID*, typed by *typename*, in model *model_name*.
  525. Typename can be set to the empty string to indicate that all types must match.
  526. Note that this returns the association itself, **NOT** the destination.
  527. Examples:
  528. To get all arcs starting in place p1:
  529. .. code::
  530. >> read_outgoing("my_pn", "p1", "P2T")
  531. ["p1_to_t1"]
  532. To get all allowed connections starting in a Place:
  533. .. code::
  534. >> read_outgoing("PetriNets", "Place", "Association")
  535. ["P2T", "InhibitorArc"]
  536. .. function:: read_incoming(model_name, ID, typename)
  537. Returns a list of all incoming associations of *ID*, typed by *typename*, in model *model_name*.
  538. Typename can be set to the empty string to indicate that all types must match.
  539. Note that this returns the association itself, **NOT** the source.
  540. Examples:
  541. To get all arcs going to place p1:
  542. .. code::
  543. >> read_incoming("my_pn", "p1", "T2P")
  544. ["t1_to_p1"]
  545. To get all allowed connections going to a Place:
  546. .. code::
  547. >> read_incoming("PetriNets", "Place", "Association")
  548. ["T2P"]
  549. .. function:: read_association_source(model_name, ID)
  550. Returns the identifier of the source of association *ID* in model *model_name*.
  551. Example:
  552. To read out the source of the P2T link:
  553. .. code::
  554. >> read_association_source("PetriNets", "P2T")
  555. "Place"
  556. To read out the source of an arc:
  557. .. code::
  558. >> read_association_source("my_pn", "p1_to_t1")
  559. "p1"
  560. .. function:: read_association_destination(model_name, ID)
  561. Returns the identifier of the target of association *ID* in model *model_name*.
  562. Example:
  563. To read out the target of the P2T link:
  564. .. code::
  565. >> read_association_destination("PetriNets", "P2T")
  566. "Transition"
  567. To read out the target of an arc:
  568. .. code::
  569. >> read_association_destination("my_pn", "p1_to_t1")
  570. "t1"
  571. .. function:: service_register(name, function)
  572. .. function:: service_stop()
  573. .. function:: service_get(port)
  574. .. function:: service_set(port, value)
  575. .. function:: user_password(user, password)
  576. .. function:: transformation_read_signature(transformation)
  577. .. function:: element_list_nice(model_name)
  578. .. function:: connections_between(model_name, source_element, target_element)
  579. .. function:: define_attribute(model_name, node, attr_name, attr_type)
  580. .. function:: all_instances(model_name, type_name)
  581. Exceptions
  582. ^^^^^^^^^^
  583. Below is a list of all exceptions that the wrappers can raise, together with a summary of the kind of error that occured.
  584. .. exception:: ModelverseException
  585. Generic Modelverse Exception, of which all others inherit.
  586. This should be the only type of exception that the wrapper can raise.
  587. .. exception:: UnknownError
  588. Unknown exception has occured.
  589. This is likely something wrong with the connection, such as the Modelverse that suddenly disconnected.
  590. .. exception:: UnknownIdentifier
  591. The specified identifier could not be resolved in the Modelverse.
  592. .. exception:: UnknownType
  593. The specified identifier could not be resolved as a type in the Modelverse.
  594. .. exception:: NotAnAssociation
  595. The specified identifier does not resolve to an association (or edge), even though this was intended.
  596. .. exception:: UnsupportedValue
  597. The specified value is not a primitive that can be serialized.
  598. Supported types are: string, boolean, integer, float, and action.
  599. .. exception:: CompilationError
  600. Error in the HUTN compiler during compilation.
  601. .. exception:: NoSuchAttribute
  602. The specified attribute does not exist for this element.
  603. .. exception:: UnknownModel
  604. The specified model can not be resolved in the Modelverse.
  605. .. exception:: ConnectionError
  606. Error with the connection to the Modelverse.
  607. .. exception:: ModelExists
  608. The identifier to give to the newly created model already exists.
  609. .. exception:: PermissionDenied
  610. Permission denied to either write or read the specified resource.
  611. .. exception:: InvalidMode
  612. An operation was executed in the wrong context.
  613. For example, all operations are only valid after a successful *init* and *login* call.
  614. .. exception:: InterfaceMismatch
  615. The Modelverse responded with an unexpected response.
  616. As a response came, the Modelverse is likely still running, though we have no idea how to interpret the result.
  617. Likely, the wrapper is not up to date with the latest Modelverse operations.
  618. Custom
  619. ------
  620. Other wrappers can be made as desired, in whatever language required.
  621. This is due to the fact that the Modelverse communicates only through XML/HTTPRequests.
  622. As such, all languages that support this, can simply mimic the interface used by any of the implemented wrappers.