modelverse_connector_rendering.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /* This file holds the code for rendering SimpleClassDiagrams from the ModelVerse.
  2. 1) The rendering meta-model and transformation are sent to the ModelVerse.
  3. 2) The transformation executes, creating the rendered model and returning the JSON.
  4. 3) 'model_CS' will then contain the rendered concrete syntax
  5. This method is dependent on the meta-model being SimpleClassDiagrams.
  6. Therefore, this code should be put aside until a more robust rendering
  7. system in the ModelVerse is created.
  8. For example, it would be ideal to have a render transformation explicitly defined
  9. for each metamodel in the ModelVerse. Then the render_model command could just
  10. return the JSON for the rendered model (or just the updated portion).
  11. */
  12. class ModelVerseRenderer {
  13. static get_CS(model_name) {
  14. //get CS for model
  15. let SCD = "formalisms/SimpleClassDiagrams";
  16. let MM_render = "formalisms/SCD_graphical";
  17. let render_trans_model = "models/render_SCD";
  18. let render_MM = this.get_render_mm();
  19. let render_trans_code = this.get_render_trans();
  20. let render_model_add = {
  21. 'data': encodeURIComponent(utils.jsons(["model_add", SCD, MM_render, render_MM]))
  22. };
  23. let transformation_between = {
  24. 'data': encodeURIComponent(utils.jsons(["transformation_add_AL", "rendered", MM_render, "abstract", SCD, "", "rendered", MM_render, "", render_trans_model]))
  25. };
  26. let transformation_data = {
  27. 'data': encodeURIComponent(utils.jsons(["transformation_add_AL", render_trans_code]))
  28. };
  29. let model_rendered = {
  30. 'data': encodeURIComponent(utils.jsons(["model_render", model_name, render_trans_model, "models/rendered_model"]))
  31. };
  32. //CS COMMANDS
  33. let model_CS = null;
  34. //TODO: only need to add models if not present
  35. ModelVerseConnector.send_command(render_model_add).then(ModelVerseConnector.get_output)
  36. .then(ModelVerseConnector.send_command(transformation_between)).then(ModelVerseConnector.get_output)
  37. .then(ModelVerseConnector.send_command({})).then(ModelVerseConnector.get_output)
  38. .then(ModelVerseConnector.send_command(transformation_data)).then(ModelVerseConnector.get_output)
  39. .then(ModelVerseConnector.send_command(model_rendered)).then(ModelVerseConnector.get_output)
  40. .then(function(data){
  41. // console.log("Data before: ");
  42. // console.log(data);
  43. data = data.replace("Success: ", "");
  44. // console.log("Data after:");
  45. // console.log(data);
  46. model_CS = eval(JSON.parse(data));
  47. });
  48. }
  49. static get_render_mm() {
  50. let mm = "include \"primitives.alh\"\n" +
  51. "\n" +
  52. "SimpleAttribute Natural {}\n" +
  53. "SimpleAttribute String {}\n" +
  54. "SimpleAttribute Boolean {}\n" +
  55. "\n" +
  56. "Class GraphicalElement {\n" +
  57. " x : Natural\n" +
  58. " y : Natural\n" +
  59. " layer : Natural\n" +
  60. "}\n" +
  61. "\n" +
  62. "Class Group : GraphicalElement {\n" +
  63. " __asid : String\n" +
  64. " dirty : Boolean\n" +
  65. "}\n" +
  66. "\n" +
  67. "Association ConnectingLine (Group, Group) {\n" +
  68. " offsetSourceX : Natural\n" +
  69. " offsetSourceY : Natural\n" +
  70. " offsetTargetX : Natural\n" +
  71. " offsetTargetY : Natural\n" +
  72. " lineWidth : Natural\n" +
  73. " lineColour : String\n" +
  74. " arrow : Boolean\n" +
  75. " __asid : String\n" +
  76. " dirty : Boolean\n" +
  77. " layer : Natural\n" +
  78. "}\n" +
  79. "\n" +
  80. "Class LineElement : GraphicalElement {\n" +
  81. " lineWidth : Natural\n" +
  82. " lineColour : String\n" +
  83. "}\n" +
  84. "\n" +
  85. "Class Text : LineElement {\n" +
  86. " text : String\n" +
  87. "}\n" +
  88. "\n" +
  89. "Class Line : LineElement {\n" +
  90. " targetX : Natural\n" +
  91. " targetY : Natural\n" +
  92. " arrow : Boolean\n" +
  93. "}\n" +
  94. "\n" +
  95. "Class Shape : LineElement {\n" +
  96. " fillColour : String\n" +
  97. " width : Natural\n" +
  98. " height : Natural\n" +
  99. "}\n" +
  100. "\n" +
  101. "Class Figure : GraphicalElement {\n" +
  102. " width : Natural\n" +
  103. " height : Natural\n" +
  104. "}\n" +
  105. "\n" +
  106. "Class SVG {\n" +
  107. " data : String\n" +
  108. "}\n" +
  109. "\n" +
  110. "Class Rectangle : Shape {\n" +
  111. "}\n" +
  112. "\n" +
  113. "Class Ellipse : Shape {\n" +
  114. "}\n" +
  115. "\n" +
  116. "Association contains (Group, GraphicalElement) {}\n" +
  117. "Association renders (Figure, SVG) {\n" +
  118. " source_lower_cardinality = 1\n" +
  119. " target_lower_cardinality = 1\n" +
  120. " target_upper_cardinality = 1\n" +
  121. "}"
  122. ;
  123. return mm;
  124. }
  125. static get_render_trans() {
  126. let trans = "include \"primitives.alh\"\n" +
  127. "include \"modelling.alh\"\n" +
  128. "include \"object_operations.alh\"\n" +
  129. "include \"utils.alh\"\n" +
  130. "\n" +
  131. "Boolean function main(model : Element):\n" +
  132. "\tElement elements\n" +
  133. "\tString class\n" +
  134. "\tElement attrs\n" +
  135. "\tElement attr_keys\n" +
  136. "\tString attr_key\n" +
  137. "\tString group\n" +
  138. "\tString elem\n" +
  139. "\tInteger loc\n" +
  140. "\tInteger text_loc\n" +
  141. "\tElement related_groups\n" +
  142. "\tloc = 10\n" +
  143. "\n" +
  144. "\tElement groups\n" +
  145. "\tgroups = dict_create()\n" +
  146. "\n" +
  147. "\telements = allInstances(model, \"rendered/Group\")\n" +
  148. "\twhile (set_len(elements) > 0):\n" +
  149. "\t\tgroup = set_pop(elements)\n" +
  150. "\t\tif (set_len(allIncomingAssociationInstances(model, group, \"TracabilityClass\")) == 0):\n" +
  151. "\t\t\tElement to_remove\n" +
  152. "\t\t\tString elem_to_remove\n" +
  153. "\t\t\tto_remove = allAssociationDestinations(model, group, \"rendered/contains\")\n" +
  154. "\t\t\twhile (set_len(to_remove) > 0):\n" +
  155. "\t\t\t\telem_to_remove = set_pop(to_remove)\n" +
  156. "\t\t\t\tif (read_type(model, elem_to_remove) == \"rendered/Group\"):\n" +
  157. "\t\t\t\t\tset_add(to_remove, elem_to_remove)\n" +
  158. "\t\t\t\telse:\n" +
  159. "\t\t\t\t\tmodel_delete_element(model, elem_to_remove)\n" +
  160. "\t\t\tmodel_delete_element(model, group)\n" +
  161. "\n" +
  162. "\telements = allInstances(model, \"abstract/Class\")\n" +
  163. "\twhile (set_len(elements) > 0):\n" +
  164. "\t\tclass = set_pop(elements)\n" +
  165. "\t\t\n" +
  166. "\t\tInteger x\n" +
  167. "\t\tInteger y\n" +
  168. "\t\tx = loc\n" +
  169. "\t\ty = 10\n" +
  170. "\n" +
  171. "\t\t// Check if there is already an associated element\n" +
  172. "\t\tif (set_len(allOutgoingAssociationInstances(model, class, \"TracabilityClass\")) > 0):\n" +
  173. "\t\t\t// Yes, but is it still clean?\n" +
  174. "\t\t\tBoolean dirty\n" +
  175. "\t\t\tdirty = False\n" +
  176. "\n" +
  177. "\t\t\trelated_groups = allAssociationDestinations(model, class, \"TracabilityClass\")\n" +
  178. "\t\t\twhile (set_len(related_groups) > 0):\n" +
  179. "\t\t\t\tgroup = set_pop(related_groups)\n" +
  180. "\t\t\t\tif (value_eq(read_attribute(model, group, \"dirty\"), True)):\n" +
  181. "\t\t\t\t\t// No, so mark all as dirty\n" +
  182. "\t\t\t\t\tdirty = True\n" +
  183. "\t\t\t\t\tbreak!\n" +
  184. "\t\t\t\telse:\n" +
  185. "\t\t\t\t\t// Yes, so just ignore this!\n" +
  186. "\t\t\t\t\tcontinue!\n" +
  187. "\n" +
  188. "\t\t\tif (bool_not(dirty)):\n" +
  189. "\t\t\t\tdict_add(groups, class, group)\n" +
  190. "\t\t\t\tcontinue!\n" +
  191. "\t\t\telse:\n" +
  192. "\t\t\t\trelated_groups = allAssociationDestinations(model, class, \"TracabilityClass\")\n" +
  193. "\t\t\t\tElement to_remove\n" +
  194. "\t\t\t\tString elem_to_remove\n" +
  195. "\t\t\t\twhile (set_len(related_groups) > 0):\n" +
  196. "\t\t\t\t\tgroup = set_pop(related_groups)\n" +
  197. "\t\t\t\t\tto_remove = allAssociationDestinations(model, group, \"rendered/contains\")\n" +
  198. "\t\t\t\t\tx = create_value(read_attribute(model, group, \"x\"))\n" +
  199. "\t\t\t\t\ty = create_value(read_attribute(model, group, \"y\"))\n" +
  200. "\t\t\t\t\twhile (set_len(to_remove) > 0):\n" +
  201. "\t\t\t\t\t\telem_to_remove = set_pop(to_remove)\n" +
  202. "\t\t\t\t\t\tif (read_type(model, elem_to_remove) == \"rendered/Group\"):\n" +
  203. "\t\t\t\t\t\t\tset_add(to_remove, elem_to_remove)\n" +
  204. "\t\t\t\t\t\telse:\n" +
  205. "\t\t\t\t\t\t\tmodel_delete_element(model, elem_to_remove)\n" +
  206. "\t\t\t\t\tmodel_delete_element(model, group)\n" +
  207. "\n" +
  208. "\t\tattr_keys = dict_keys(getAttributeList(model, class))\n" +
  209. "\t\ttext_loc = 5\n" +
  210. "\n" +
  211. "\t\tgroup = instantiate_node(model, \"rendered/Group\", \"\")\n" +
  212. "\t\tinstantiate_attribute(model, group, \"x\", x)\n" +
  213. "\t\tinstantiate_attribute(model, group, \"y\", y)\n" +
  214. "\t\tinstantiate_attribute(model, group, \"__asid\", list_read(string_split_nr(class, \"/\", 1), 1))\n" +
  215. "\t\tinstantiate_attribute(model, group, \"layer\", 0)\n" +
  216. "\t\tdict_add(groups, class, group)\n" +
  217. "\t\tloc = loc + 200\n" +
  218. "\n" +
  219. "\t\telem = instantiate_node(model, \"rendered/Rectangle\", \"\")\n" +
  220. "\t\tinstantiate_attribute(model, elem, \"x\", 0)\n" +
  221. "\t\tinstantiate_attribute(model, elem, \"y\", 0)\n" +
  222. "\t\tinstantiate_attribute(model, elem, \"height\", 40 + set_len(getInstantiatableAttributes(model, class, \"abstract/AttributeLink\")) * 20)\n" +
  223. "\t\tinstantiate_attribute(model, elem, \"width\", 150)\n" +
  224. "\t\tinstantiate_attribute(model, elem, \"lineWidth\", 2) \n" +
  225. "\t\tinstantiate_attribute(model, elem, \"lineColour\", \"black\")\n" +
  226. "\t\tinstantiate_attribute(model, elem, \"fillColour\", \"white\")\n" +
  227. "\t\tinstantiate_attribute(model, elem, \"layer\", 1)\n" +
  228. "\t\tinstantiate_link(model, \"rendered/contains\", \"\", group, elem)\n" +
  229. "\n" +
  230. "\t\tString multiplicities\n" +
  231. "\t\tString lower_card\n" +
  232. "\t\tString upper_card\n" +
  233. "\t\tif (element_eq(read_attribute(model, class, \"lower_cardinality\"), read_root())):\n" +
  234. "\t\t\tlower_card = \"*\"\n" +
  235. "\t\telse:\n" +
  236. "\t\t\tlower_card = cast_value(read_attribute(model, class, \"lower_cardinality\"))\n" +
  237. "\t\tif (element_eq(read_attribute(model, class, \"upper_cardinality\"), read_root())):\n" +
  238. "\t\t\tupper_card = \"*\"\n" +
  239. "\t\telse:\n" +
  240. "\t\t\tupper_card = cast_value(read_attribute(model, class, \"upper_cardinality\"))\n" +
  241. "\t\tmultiplicities = (((\"[\" + lower_card) + \"..\") + upper_card) + \"]\"\n" +
  242. "\n" +
  243. "\t\telem = instantiate_node(model, \"rendered/Text\", \"\")\n" +
  244. "\t\tinstantiate_attribute(model, elem, \"x\", 5)\n" +
  245. "\t\tinstantiate_attribute(model, elem, \"y\", 3)\n" +
  246. "\t\tinstantiate_attribute(model, elem, \"lineWidth\", 1)\n" +
  247. "\t\tinstantiate_attribute(model, elem, \"lineColour\", \"black\")\n" +
  248. "\t\tif (element_neq(read_attribute(model, class, \"name\"), read_root())):\n" +
  249. "\t\t\tinstantiate_attribute(model, elem, \"text\", string_join(read_attribute(model, class, \"name\"), \" \" + multiplicities))\n" +
  250. "\t\telse:\n" +
  251. "\t\t\tinstantiate_attribute(model, elem, \"text\", \"(unnamed) \" + multiplicities)\n" +
  252. "\t\tinstantiate_attribute(model, elem, \"layer\", 2)\n" +
  253. "\t\tinstantiate_link(model, \"rendered/contains\", \"\", group, elem)\n" +
  254. "\n" +
  255. "\t\telem = instantiate_node(model, \"rendered/Line\", \"\")\n" +
  256. "\t\tinstantiate_attribute(model, elem, \"x\", 0)\n" +
  257. "\t\tinstantiate_attribute(model, elem, \"y\", 20)\n" +
  258. "\t\tinstantiate_attribute(model, elem, \"targetX\", 150)\n" +
  259. "\t\tinstantiate_attribute(model, elem, \"targetY\", 20)\n" +
  260. "\t\tinstantiate_attribute(model, elem, \"lineWidth\", 1)\n" +
  261. "\t\tinstantiate_attribute(model, elem, \"lineColour\", \"black\")\n" +
  262. "\t\tinstantiate_attribute(model, elem, \"arrow\", False)\n" +
  263. "\t\tinstantiate_attribute(model, elem, \"layer\", 2)\n" +
  264. "\t\tinstantiate_link(model, \"rendered/contains\", \"\", group, elem)\n" +
  265. "\n" +
  266. "\t\tattrs = getInstantiatableAttributes(model, class, \"abstract/AttributeLink\")\n" +
  267. "\t\tattr_keys = dict_keys(attrs)\n" +
  268. "\t\twhile (dict_len(attr_keys) > 0):\n" +
  269. "\t\t\tattr_key = set_pop(attr_keys)\n" +
  270. "\t\t\telem = instantiate_node(model, \"rendered/Text\", \"\")\n" +
  271. "\t\t\tinstantiate_attribute(model, elem, \"x\", 5)\n" +
  272. "\t\t\tinstantiate_attribute(model, elem, \"y\", text_loc + 20)\n" +
  273. "\t\t\tinstantiate_attribute(model, elem, \"lineWidth\", 1)\n" +
  274. "\t\t\tinstantiate_attribute(model, elem, \"lineColour\", \"black\")\n" +
  275. "\t\t\tinstantiate_attribute(model, elem, \"text\", (attr_key + \" : \") + cast_string(list_read(string_split_nr(attrs[attr_key], \"/\", 1), 1)))\n" +
  276. "\t\t\tinstantiate_attribute(model, elem, \"layer\", 2)\n" +
  277. "\t\t\tinstantiate_link(model, \"rendered/contains\", \"\", group, elem)\n" +
  278. "\t\t\ttext_loc = text_loc + 15\n" +
  279. "\n" +
  280. "\t\tinstantiate_link(model, \"TracabilityClass\", \"\", class, group)\n" +
  281. "\n" +
  282. "\t// Flush all associations\n" +
  283. "\telements = allInstances(model, \"rendered/ConnectingLine\")\n" +
  284. "\twhile (set_len(elements) > 0):\n" +
  285. "\t\tclass = set_pop(elements)\n" +
  286. "\t\tmodel_delete_element(model, class)\n" +
  287. "\n" +
  288. "\t// Rerender associations\n" +
  289. "\telements = allInstances(model, \"abstract/Association\")\n" +
  290. "\twhile (set_len(elements) > 0):\n" +
  291. "\t\tclass = set_pop(elements)\n" +
  292. "\n" +
  293. "\t\tattr_keys = dict_keys(getAttributeList(model, class))\n" +
  294. "\n" +
  295. "\t\telem = instantiate_link(model, \"rendered/ConnectingLine\", \"\", groups[readAssociationSource(model, class)], groups[readAssociationDestination(model, class)])\n" +
  296. "\t\tinstantiate_attribute(model, elem, \"offsetSourceX\", 75)\n" +
  297. "\t\tinstantiate_attribute(model, elem, \"offsetSourceY\", 30)\n" +
  298. "\t\tinstantiate_attribute(model, elem, \"offsetTargetX\", 75)\n" +
  299. "\t\tinstantiate_attribute(model, elem, \"offsetTargetY\", 30)\n" +
  300. "\t\tinstantiate_attribute(model, elem, \"lineWidth\", 1)\n" +
  301. "\t\tinstantiate_attribute(model, elem, \"lineColour\", \"black\")\n" +
  302. "\t\tinstantiate_attribute(model, elem, \"arrow\", True)\n" +
  303. "\t\tinstantiate_attribute(model, elem, \"__asid\", list_read(string_split_nr(class, \"/\", 1), 1))\n" +
  304. "\t\tinstantiate_attribute(model, elem, \"layer\", 0)\n" +
  305. "\t\tlog(\"Real ASID: \" + cast_value(class))\n" +
  306. "\t\tlog(\"Found ASID \" + cast_value(list_read(string_split_nr(class, \"/\", 1), 1)))\n" +
  307. "\t\tinstantiate_link(model, \"rendered/contains\", \"\", group, elem)\n" +
  308. "\n" +
  309. "\treturn True!";
  310. return trans;
  311. }
  312. }