modelverse_connector.js 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075
  1. class ModelVerseConnector {
  2. constructor(address) {
  3. ModelVerseConnector.taskname = "task_manager";
  4. ModelVerseConnector.address = (address == undefined) ? "http://127.0.0.1:8001" : address;
  5. ModelVerseConnector.ERROR = 0;
  6. ModelVerseConnector.WORKING = 1;
  7. ModelVerseConnector.OKAY = 2;
  8. ModelVerseConnector.connected = true;
  9. ModelVerseConnector.curr_model = null;
  10. ModelVerseConnector.element_map = {};
  11. ModelVerseConnector.PM2MV_metamodel_map = {
  12. "/Formalisms/__LanguageSyntax__/SimpleClassDiagram/SimpleClassDiagram" : "formalisms/SimpleClassDiagrams",
  13. };
  14. ModelVerseConnector.MV2PM_metamodel_map = ModelVerseConnector.reverse_dict(ModelVerseConnector.PM2MV_metamodel_map);
  15. }
  16. static reverse_dict(dict){
  17. let ret = {};
  18. for(let key of Object.keys(dict)){
  19. ret[dict[key]] = key;
  20. }
  21. return ret;
  22. }
  23. static set_status(status) {
  24. let red = "rgb(220,20,60)";
  25. let yellow = "rgb(218,165,32)";
  26. let green = "rgb(50,205,50)";
  27. let colours = [red, yellow, green];
  28. let set_colour = function (colour) {
  29. let mv_toolbar = $('#div_toolbar_\\2f Toolbars\\2f ModelVerse\\2f ModelVerse\\2e buttons\\2e model');
  30. mv_toolbar.css("background-color", colour)
  31. };
  32. set_colour(colours[status]);
  33. }
  34. static save_model(model_name, data){
  35. ModelVerseConnector.set_status(ModelVerseConnector.WORKING);
  36. console.log("Save model: " + model_name);
  37. let parsed_data = JSON.parse(data);
  38. // console.log(parsed_data);
  39. let m = JSON.parse(parsed_data['data']['m']);
  40. let mms = JSON.parse(parsed_data['data']['mms']);
  41. //detect the metamodels
  42. if (Object.keys(mms).length > 1){
  43. console.log("Warning: More than one meta-model detected!")
  44. }
  45. let primary_mm_PM = Object.keys(mms)[0];
  46. let primary_mm_MV = ModelVerseConnector.PM2MV_metamodel_map[primary_mm_PM];
  47. //TODO: Allow user to select meta-model when it is not found
  48. // console.log("MV PM: " + primary_mm_PM);
  49. // console.log("MV MM: " + primary_mm_MV);
  50. if (primary_mm_MV == undefined){
  51. //WindowManagement.openDialog(_ERROR,'Meta-model may not exist in ModelVerse: "' + primary_mm_PM + '"');
  52. //return;
  53. if (primary_mm_PM.startsWith("/")){
  54. primary_mm_PM = primary_mm_PM.slice(1);
  55. }
  56. primary_mm_MV = primary_mm_PM;
  57. }
  58. let model_delete = {
  59. "data": utils.jsons(["model_delete", model_name])
  60. };
  61. let model_create = {
  62. "data": utils.jsons(["model_add", primary_mm_MV, model_name, ""])
  63. };
  64. let model_edit = {
  65. "data": utils.jsons(["model_modify", model_name, primary_mm_MV])
  66. };
  67. ModelVerseConnector.curr_model = model_name;
  68. ModelVerseConnector.send_command(model_create)
  69. .then(ModelVerseConnector.get_output)
  70. .then(function (data) {
  71. if (data.includes("Model not found")){
  72. ModelVerseConnector.set_status(ModelVerseConnector.ERROR);
  73. WindowManagement.openDialog(_ERROR,data);
  74. return;
  75. }
  76. })
  77. .then(ModelVerseConnector.send_command(model_edit))
  78. .then(ModelVerseConnector.get_output)
  79. .then(function(data){
  80. //find edges
  81. //these have srcs and dests in the edge list
  82. let edge_map = {};
  83. for (const [key, node] of Object.entries(m.nodes)) {
  84. let src = null;
  85. let dest = null;
  86. for (const [edge_key, edge] of Object.entries(m.edges)) {
  87. //iterate through each pair of edges
  88. if (edge_key == m.edges.length - 1){
  89. continue;
  90. }
  91. //only look at pairs
  92. if (parseInt(edge_key) % 2 == 1){
  93. continue;
  94. }
  95. let next_edge = m.edges[parseInt(edge_key) + 1];
  96. //see if the links overlap -> this node is an edge
  97. if (edge["dest"] == next_edge["src"] && next_edge["src"] == key){
  98. src = edge['src'];
  99. dest = next_edge['dest']
  100. }
  101. }
  102. if (src == null || dest == null){
  103. continue;
  104. }
  105. edge_map[key] = [src, dest];
  106. }
  107. //for detecting duplications
  108. let nodes_names = [];
  109. let node_creation_promises = [];
  110. for (const [key, node] of Object.entries(m.nodes)) {
  111. // if (node.name == undefined){
  112. // continue;
  113. // }
  114. // console.log("Node creation:");
  115. // console.log(node);
  116. if (!(node.linktype == undefined)){
  117. continue;
  118. }
  119. if (Object.keys(edge_map).includes(key)){
  120. continue;
  121. }
  122. let node_name = key;
  123. if (node.name != undefined){
  124. node_name = node.name.value;
  125. }
  126. if (nodes_names.includes((node_name))){
  127. node_name += "_" + key;
  128. }
  129. nodes_names.push(node_name);
  130. let node_type = node.$type.split("/").slice(-1)[0];
  131. node_creation_promises.push(ModelVerseConnector.send_command(
  132. {"data": utils.jsons(["instantiate_node", node_type, node_name])}
  133. ));
  134. let set_id = function (id){
  135. if (id.includes("Success")){
  136. ModelVerseConnector.element_map[key] = id.split(" ")[1].replace("\"", "");
  137. }
  138. };
  139. node_creation_promises.push(ModelVerseConnector.get_output(set_id));
  140. }
  141. //TODO: Only for SimpleClassDiagrams?
  142. let simple_type = ["String", "Int", "Float", "Boolean", "Code", "File", "Map", "List", "ENUM"];
  143. for (let st of simple_type){
  144. node_creation_promises.push(ModelVerseConnector.send_command(
  145. {"data": utils.jsons(["instantiate_node", "SimpleAttribute", st])}
  146. ));
  147. node_creation_promises.push(ModelVerseConnector.get_output());
  148. }
  149. //get cardinalities
  150. let card_dict = {};
  151. let attrib_creation_promises = [];
  152. // console.log("Cardinalities");
  153. for (const [key, node] of Object.entries(m.nodes)) {
  154. if (node.cardinalities == undefined || node.cardinalities.value.length == 0){
  155. continue;
  156. }
  157. //console.log(node);
  158. for (const card of node.cardinalities.value){
  159. //console.log(card);
  160. let cardname = card["type"] + card["dir"];
  161. card_dict[cardname] = [card["min"], card["max"]];
  162. // console.log(card_dict);
  163. }
  164. }
  165. Promise.all(node_creation_promises).then( function(){
  166. let edge_creation_promises = [];
  167. for (const [key, node] of Object.entries(m.nodes)) {
  168. if (!(Object.keys(edge_map).includes(key))){
  169. continue;
  170. }
  171. // console.log("Creating edge:");
  172. // console.log(node);
  173. let node_type = node.$type.split("/").slice(-1)[0];
  174. let node_name = null;
  175. if (node.name != undefined) {
  176. node_name = node.name.value;
  177. }else{
  178. node_name = node_type + key;
  179. }
  180. let es = edge_map[key][0];
  181. let ed = edge_map[key][1];
  182. let src = ModelVerseConnector.element_map[es];
  183. let dest = ModelVerseConnector.element_map[ed];
  184. let set_id = function (id){
  185. if (id.includes("Success")){
  186. ModelVerseConnector.element_map[key] = id.split(" ")[1].replace("\"", "");
  187. }
  188. };
  189. if (src != null && dest != null) {
  190. edge_creation_promises.push(ModelVerseConnector.send_command(
  191. {"data": utils.jsons(["instantiate_edge", node_type, node_name, src, dest])}
  192. ));
  193. edge_creation_promises.push(ModelVerseConnector.get_output(set_id));
  194. }
  195. }
  196. Promise.all(edge_creation_promises).then(function() {
  197. // Add attributes
  198. console.log("Adding attributes");
  199. for (const [key, node] of Object.entries(m.nodes)) {
  200. console.log(node);
  201. let ele = ModelVerseConnector.element_map[key];
  202. let node_type = node.$type.split("/").slice(-1)[0];
  203. if (node.abstract != undefined && node.abstract.value){
  204. attrib_creation_promises.push(ModelVerseConnector.send_command(
  205. {"data": utils.jsons(["attr_add", ele, "abstract", true])}
  206. ));
  207. attrib_creation_promises.push(ModelVerseConnector.get_output());
  208. }
  209. for (const [attrib_key, attrib_value] of Object.entries(node)){
  210. if (attrib_key.startsWith("__") || attrib_value.value == undefined){
  211. continue;
  212. }
  213. attrib_creation_promises.push(ModelVerseConnector.send_command(
  214. {"data": utils.jsons(["attr_add", ele, attrib_key, attrib_value.value])}
  215. ));
  216. attrib_creation_promises.push(ModelVerseConnector.get_output());
  217. }
  218. if (node.name != undefined){
  219. // console.log(Object.keys(card_dict));
  220. let src_card = card_dict[node.name.value + "out"];
  221. let trgt_card = card_dict[node.name.value + "in"];
  222. // console.log("Src:");
  223. // console.log(src_card);
  224. if (src_card != undefined){
  225. attrib_creation_promises.push(ModelVerseConnector.send_command(
  226. {"data": utils.jsons(["attr_add", ele, "source_lower_cardinality", src_card[0]])}
  227. ));
  228. attrib_creation_promises.push(ModelVerseConnector.get_output());
  229. attrib_creation_promises.push(ModelVerseConnector.send_command(
  230. {"data": utils.jsons(["attr_add", ele, "source_upper_cardinality", src_card[1]])}
  231. ));
  232. attrib_creation_promises.push(ModelVerseConnector.get_output());
  233. }
  234. // console.log("Trgt:");
  235. // console.log(trgt_card);
  236. if (trgt_card != undefined){
  237. attrib_creation_promises.push(ModelVerseConnector.send_command(
  238. {"data": utils.jsons(["attr_add", ele, "target_lower_cardinality", trgt_card[0]])}
  239. ));
  240. attrib_creation_promises.push(ModelVerseConnector.get_output());
  241. attrib_creation_promises.push(ModelVerseConnector.send_command(
  242. {"data": utils.jsons(["attr_add", ele, "target_upper_cardinality", trgt_card[1]])}
  243. ));
  244. attrib_creation_promises.push(ModelVerseConnector.get_output());
  245. }
  246. }
  247. if (node.attributes != undefined) {
  248. //console.log(node);
  249. for (const [key, attrib] of Object.entries(node.attributes.value)) {
  250. //console.log(attrib);
  251. let type = attrib.type[0].toUpperCase() + attrib.type.substring(1);
  252. if (type.startsWith("ENUM")){
  253. type = "ENUM";
  254. }
  255. type = type.split("<")[0];
  256. attrib_creation_promises.push(ModelVerseConnector.send_command(
  257. {"data": utils.jsons(["define_attribute", ele, attrib.name, type])}
  258. ));
  259. attrib_creation_promises.push(ModelVerseConnector.get_output());
  260. }
  261. }
  262. }
  263. ModelVerseConnector.set_status(ModelVerseConnector.OKAY);
  264. });
  265. });
  266. });
  267. }
  268. static load_MV_model(metamodels, AS) {
  269. return new Promise(
  270. function (resolve, reject) {
  271. console.log("Load MV Model");
  272. console.log(AS);
  273. console.log(metamodels);
  274. let primary_MV_metamodel = metamodels.split(" ")[1].split(",")[0];
  275. let primary_PM_metamodel = ModelVerseConnector.MV2PM_metamodel_map[primary_MV_metamodel];
  276. if (primary_PM_metamodel == undefined){
  277. console.log("Warning: No metamodel known for " + primary_MV_metamodel);
  278. primary_PM_metamodel = primary_MV_metamodel;
  279. }
  280. console.log("MV MM: " + primary_MV_metamodel);
  281. console.log("PM MM: " + primary_PM_metamodel);
  282. let csmetamodel = ".defaultIcons";
  283. //this concrete syntax is better
  284. if (primary_MV_metamodel == "formalisms/SimpleClassDiagrams"){
  285. csmetamodel = ".umlIcons";
  286. }
  287. let metamodel = primary_PM_metamodel + csmetamodel + ".metamodel";
  288. DataUtils.loadmm(metamodel,
  289. function(){
  290. console.log("Metamodel loaded: " + metamodel);
  291. });
  292. let model_elements = [];
  293. let model_links = [];
  294. let model_links_dict = {};
  295. let model_attrib_types = [];
  296. let model_attribs = {};
  297. //class name, etc.
  298. let model_properties = {};
  299. for (const obj of Object.values(AS)) {
  300. let obj_type = obj["__type"];
  301. let name = obj["__id"];
  302. // if (name == undefined){
  303. // name = obj["name"];
  304. // }
  305. if (obj_type == "SimpleAttribute"){
  306. model_attrib_types.push(name);
  307. continue;
  308. }
  309. let src = obj["__source"];
  310. let trgt = obj["__target"];
  311. let add_properties = true;
  312. // console.log("obj " + obj_type + " " + name + " = " + src + " - " + trgt);
  313. if (src == undefined && trgt == undefined){
  314. model_elements.push([name, obj_type]);
  315. }else{
  316. if (obj_type == "AttributeLink"){//model_attrib_types.includes(trgt)){
  317. if (model_attribs[src] == undefined){
  318. model_attribs[src] = [];
  319. }
  320. model_attribs[src].push([name, trgt]);
  321. add_properties = false;
  322. }else{
  323. model_links.push([obj_type, src, trgt, obj["__id"]]);
  324. model_links_dict[obj["__id"]] = [src, trgt];
  325. }
  326. }
  327. if (add_properties) {
  328. for (let [prop_name, prop_value] of Object.entries(obj)) {
  329. // console.log(name + " :: " + prop_name + ' = ' + prop_value);
  330. if (prop_name.startsWith("__")) {
  331. continue;
  332. }
  333. if (prop_value == null){
  334. continue;
  335. }
  336. if (model_properties[name] == undefined) {
  337. model_properties[name] = [];
  338. }
  339. if (prop_name.endsWith("_cardinality")){
  340. if (!(Object.keys(model_links_dict).includes(name))){
  341. continue;
  342. }
  343. let dest = undefined;
  344. let lower_upper = prop_name.split("_")[1];
  345. lower_upper = (lower_upper == "lower")? "min":"max";
  346. if (prop_name.startsWith("source")){
  347. dest = model_links_dict[name][0];
  348. prop_name = "cardinality_" + lower_upper + "_" + name + "_out_";
  349. }else if (prop_name.startsWith("target")){
  350. dest = model_links_dict[name][1];
  351. prop_name = "cardinality_" + lower_upper + "_" + name + "_in_";
  352. }
  353. if (model_properties[dest] == undefined) {
  354. model_properties[dest] = [];
  355. }
  356. model_properties[dest].push([prop_name, prop_value]);
  357. continue;
  358. }
  359. // console.log(name + " :: " + prop_name + ' = ' + prop_value);
  360. model_properties[name].push([prop_name, prop_value]);
  361. }
  362. }
  363. }
  364. let ele_ids = {};
  365. //TODO: Replace with better layout
  366. let start_x = 100;
  367. let start_y = 100;
  368. let x_offset = 250;
  369. let max_x = 4;
  370. let y_offset = 200;
  371. let i = 0;
  372. let element_promises = [];
  373. for (const [name, obj_type] of model_elements){
  374. let class_type = primary_PM_metamodel + csmetamodel + "/" + obj_type + "Icon";
  375. __typeToCreate = class_type;
  376. element_promises.push(new Promise(function(resolve, reject){
  377. let updateClass =
  378. function(status, resp){
  379. if (Math.floor(status / 100) != 2){
  380. resolve();
  381. return;
  382. }
  383. // console.log(status);
  384. // console.log(resp);
  385. let data = JSON.parse(resp);
  386. let uri = class_type + "/" + data["data"] + ".instance";
  387. ele_ids[name] = uri;
  388. resolve();
  389. };
  390. let x_pos = start_x + Math.floor(i % max_x) * x_offset;
  391. let y_pos = start_y + Math.floor(i / max_x) * y_offset;
  392. DataUtils.create(x_pos, y_pos, updateClass);
  393. i +=1;
  394. }));
  395. }
  396. Promise.all(element_promises).then(function(){
  397. console.log("Starting link promises");
  398. let link_promises = [];
  399. for (const [obj_type, src, trgt, obj_id] of model_links){
  400. // console.log("Link:");
  401. // console.log(obj_type + " " + src + " " + trgt + " " + obj_id);
  402. link_promises.push(new Promise(function(resolve, reject) {
  403. let source_element = ele_ids[src];
  404. let target_element = ele_ids[trgt];
  405. //skip attribute links
  406. if (obj_type == "AttributeLink"){
  407. resolve();
  408. return;
  409. }
  410. if (source_element == undefined || target_element == undefined) {
  411. console.log("ERROR: Can't create link '" + obj_type + "' between " + src + " and " + trgt);
  412. resolve();
  413. return;
  414. }
  415. let connectionType = primary_PM_metamodel + csmetamodel + "/" + obj_type + "Link.type";
  416. let link_create_callback = function(status, resp){
  417. // console.log(status);
  418. // console.log(resp);
  419. let id = JSON.parse(resp)["data"];
  420. let assoc_id = connectionType.replace(".type", "/") + id + ".instance";
  421. // console.log(obj_id + " = " + assoc_id);
  422. ele_ids[obj_id] = assoc_id;
  423. resolve();
  424. };
  425. console.log("Building " + connectionType + " between "
  426. + source_element + " (" + src + ") and " + target_element + " (" + trgt + ")");
  427. HttpUtils.httpReq(
  428. 'POST',
  429. HttpUtils.url(connectionType, __NO_USERNAME),
  430. {
  431. 'src': source_element,
  432. 'dest': target_element,
  433. 'pos': undefined,
  434. 'segments': undefined
  435. },
  436. link_create_callback);
  437. }));
  438. }
  439. Promise.all(link_promises).then(function(){
  440. console.log("Start properties");
  441. for (const [ele, properties] of Object.entries(model_properties)) {
  442. let uri = ele_ids[ele];
  443. if (uri == undefined) {
  444. console.log("Uri not found for element: " + ele);
  445. continue;
  446. }
  447. // console.log("Element: " + ele + " = uri: " + uri);
  448. let changes = {};
  449. let cardinalities = [];
  450. let card_dict = {};
  451. for (const [key, value] of Object.entries(properties)) {
  452. // console.log(value[0] + " = ");
  453. // console.log(value[1]);
  454. //TODO: Fix this
  455. if (value[0].includes("constraint")) {
  456. continue;
  457. }
  458. if (value[0].startsWith("cardinality")) {
  459. let minmax = value[0].split("_")[1];
  460. let assoc_name = value[0].split("_")[2];
  461. let dir = value[0].split("_")[3];
  462. // console.log("Card:");
  463. // console.log(minmax + " " + assoc_name + " " + dir);
  464. let found_card = false;
  465. for (let [key, existing_card] of Object.entries(cardinalities)){
  466. if (existing_card["type"] == assoc_name){
  467. found_card = true;
  468. cardinalities[key][minmax] = value[1];
  469. }
  470. }
  471. if (!found_card)
  472. {
  473. let new_card = {
  474. "dir" : dir,
  475. "type" : assoc_name
  476. };
  477. new_card[minmax] = value[1];
  478. cardinalities.push(new_card);
  479. }
  480. }else {
  481. //all other properties
  482. changes[value[0]] = value[1];
  483. }
  484. }
  485. if (cardinalities.length > 0) {
  486. changes["cardinalities"] = cardinalities;
  487. }
  488. DataUtils.update(uri, changes);
  489. }
  490. console.log("Start attributes");
  491. for (const [ele, attributes] of Object.entries(model_attribs)){
  492. let uri = ele_ids[ele];
  493. if (uri == undefined){
  494. console.log("Uri not found for element: " + ele);
  495. continue;
  496. }
  497. let attrib_changes = [];
  498. // console.log("Element: " + ele + " = uri: " + uri);
  499. for (const[key, value] of attributes){
  500. //TODO: Make attributes valid PM types
  501. let pm_value = value.toLowerCase();
  502. if (pm_value == "natural" || pm_value == "integer"){
  503. pm_value = "int";
  504. }
  505. // console.log(key + " = " + pm_value);
  506. let attrib_change = {
  507. "name": key,
  508. "type" : pm_value
  509. };
  510. attrib_changes.push(attrib_change);
  511. }
  512. DataUtils.update(uri, {"attributes" : attrib_changes});
  513. }
  514. });
  515. });
  516. resolve();
  517. });
  518. }
  519. /*********COMMUNICATION FUNCTIONS**********/
  520. static send_command(param_dict) {
  521. return new Promise(
  522. function (resolve, reject) {
  523. let callback = function (status, resp) {
  524. if (utils.isHttpSuccessCode(status)) {
  525. //console.log("send_command Resolve: " + resp);
  526. resolve(resp);
  527. } else {
  528. console.log("send_command Reject: " + resp);
  529. reject(resp);
  530. }
  531. };
  532. if (!("op" in param_dict)) {
  533. param_dict["op"] = "set_input";
  534. }
  535. if (!("taskname" in param_dict)) {
  536. param_dict["taskname"] = ModelVerseConnector.taskname;
  537. }
  538. let params = "";
  539. for (const [key, value] of Object.entries(param_dict)) {
  540. params += key + "=" + value + "&";
  541. }
  542. //take off last &
  543. params = params.slice(0, -1);
  544. console.log("Sending: " + params);
  545. HttpUtils.httpReq("POST", ModelVerseConnector.address,
  546. params,
  547. callback
  548. );
  549. });
  550. }
  551. static get_output(clbk) {
  552. return new Promise(
  553. function (resolve, reject) {
  554. let callback = function (status, resp) {
  555. if (utils.isHttpSuccessCode(status)) {
  556. console.log("get_output Resolve: " + resp);
  557. if (clbk != undefined && typeof clbk == "function"){
  558. clbk(resp);
  559. }
  560. resolve(resp);
  561. } else {
  562. console.log("get_output reject: " + resp);
  563. reject(resp);
  564. }
  565. };
  566. let params = "op=get_output&taskname=" + ModelVerseConnector.taskname;
  567. HttpUtils.httpReq("POST", ModelVerseConnector.address,
  568. params,
  569. callback
  570. );
  571. }
  572. );
  573. }
  574. /*********END COMMUNICATION FUNCTIONS**********/
  575. /*********WRAPPER FUNCTIONS**********/
  576. static connect(username_param, password_param) {
  577. console.log("Connecting to: " + ModelVerseConnector.address);
  578. ModelVerseConnector.set_status(ModelVerseConnector.WORKING);
  579. let username = username_param || "admin";
  580. let password = password_param || "admin";
  581. let username_params = {
  582. "value": "\"" + username + "\""
  583. };
  584. let password_params = {
  585. "value": "\"" + password + "\""
  586. };
  587. let quiet_mode_params = {
  588. "value": "\"quiet\""
  589. };
  590. this.get_output().then(
  591. function(data){
  592. data = data.replace(/"/g, "");
  593. ModelVerseConnector.taskname = data;
  594. }
  595. )
  596. .then(() => this.send_command(username_params)).then(this.get_output)
  597. .then(() => this.send_command(password_params)).then(this.get_output)
  598. .then(() => this.send_command(quiet_mode_params)).then(this.get_output)
  599. .then(this.get_output)
  600. .then(function () {
  601. ModelVerseConnector.set_status(ModelVerseConnector.OKAY);
  602. })
  603. .catch(
  604. function () {
  605. WindowManagement.openDialog(_ERROR, 'failed to login to the ModelVerse!');
  606. ModelVerseConnector.set_status(ModelVerseConnector.ERROR);
  607. }
  608. );
  609. };
  610. //TODO: Cache this data if too slow
  611. static async get_files_in_folder(folder_name){
  612. return await ModelVerseConnector.model_list(folder_name);
  613. }
  614. static model_list(folder_name){
  615. return new Promise(function(resolve, reject) {
  616. console.log("Listing models in: '" + folder_name + "'");
  617. let folder_param = folder_name;
  618. //fix slashes on filename
  619. if (folder_param.endsWith("/")){
  620. folder_param = folder_param.slice(0, -1);
  621. }
  622. if (folder_param.startsWith("/")){
  623. folder_param = folder_param.slice(1);
  624. }
  625. let model_types = {
  626. "data": utils.jsons(["model_list", folder_param])
  627. };
  628. ModelVerseConnector.send_command(model_types).then(ModelVerseConnector.get_output)
  629. .then(function (data) {
  630. let files = [];
  631. data = data.replace("Success: ", "");
  632. let new_files = JSON.parse(data).split("\n");
  633. for (let i in new_files) {
  634. let file = new_files[i];
  635. files.push(folder_name + file);
  636. }
  637. files.sort();
  638. resolve(files);
  639. });
  640. });
  641. }
  642. static choose_model(status, model_to_save){
  643. console.log("Choosing model: ");
  644. if (status != undefined && status != 200){
  645. ModelVerseConnector.set_status(ModelVerseConnector.ERROR);
  646. return;
  647. };
  648. let loading_mode = (model_to_save == undefined);
  649. let folders = [""];
  650. let files = [];
  651. ModelVerseConnector.set_status(ModelVerseConnector.WORKING);
  652. //if editing a model, exit it
  653. if (ModelVerseConnector.curr_model){
  654. let command = {"data": utils.jsons(["exit"])};
  655. ModelVerseConnector.send_command(command).then(this.get_output)
  656. .then(function(data){
  657. ModelVerseConnector.curr_model = null;
  658. });
  659. }
  660. let startDir = "/";
  661. let fileb = FileBrowser.getFileBrowser(ModelVerseConnector.get_files_in_folder, false, !loading_mode, startDir);
  662. let feedback = GUIUtils.getTextSpan('', "feedback");
  663. let title = "ModelVerse Explorer";
  664. let callback = function (filenames) {
  665. //fix slashes on filename
  666. // if (filenames[0].endsWith("/")){
  667. // filenames[0] = filenames[0].slice(0, -1);
  668. // }
  669. if (filenames[0].startsWith("/")){
  670. filenames[0] = filenames[0].slice(1);
  671. }
  672. if (loading_mode) {
  673. ModelVerseConnector.load_model(filenames[0]);
  674. }else{
  675. ModelVerseConnector.save_model(filenames[0], model_to_save);
  676. }
  677. };
  678. let folder_buttons = $('<div>');
  679. let new_folder_b = $('<button>');
  680. new_folder_b.attr('id', 'new_folder')
  681. .html('new folder')
  682. .click(function (ev) {
  683. let folder_name = prompt("please fill in a name for the folder");
  684. if (folder_name == null) {
  685. return;
  686. }
  687. folder_name = folder_name.replace(/^\s+|\s+$/g, ''); // trim
  688. if (!folder_name.match(/^[a-zA-Z0-9_\s]+$/i)) {
  689. feedback.html("invalid folder name: " + folder_name);
  690. } else {
  691. let full_folder_name = fileb['getcurrfolder']() + folder_name;
  692. console.log("Creating: " + full_folder_name);
  693. let mk_folder_command = {
  694. "data": utils.jsons(["folder_create", full_folder_name])
  695. };
  696. ModelVerseConnector.send_command(mk_folder_command).then(ModelVerseConnector.get_output)
  697. .then(function (data) {
  698. console.log("Got data: " + data);
  699. });
  700. }
  701. });
  702. folder_buttons.append(new_folder_b);
  703. GUIUtils.setupAndShowDialog(
  704. [fileb['filebrowser'], loading_mode?null:folder_buttons, null, feedback],
  705. function () {
  706. let value = [fileb['getselection']()];
  707. if (value.length > 0 && value[0] != "" && startDir) {
  708. __setRecentDir(startDir, value[0].substring(0, value[0].lastIndexOf('/') + 1));
  709. }
  710. return value;
  711. },
  712. __TWO_BUTTONS,
  713. title,
  714. callback);
  715. ModelVerseConnector.set_status(ModelVerseConnector.OKAY);
  716. }
  717. static load_model(model_name) {
  718. //TODO: Allow user to choose metamodel
  719. let metamodel = "formalisms/SimpleClassDiagrams";
  720. if (model_name.includes("autotest") && model_name != "autotest/autotest"){
  721. metamodel = "autotest/autotest";
  722. }
  723. console.log("Loading model: " + model_name);
  724. ModelVerseConnector.set_status(ModelVerseConnector.WORKING);
  725. ModelVerseConnector.curr_model = model_name;
  726. //get AS for model
  727. let model_types_command = {
  728. "data": utils.jsons(["model_types", model_name])
  729. };
  730. let model_modify = {
  731. "data": utils.jsons(["model_modify", model_name, metamodel])
  732. };
  733. let model_dump = {
  734. "data": utils.jsons(["JSON"])
  735. };
  736. let model_types = null;
  737. //AS COMMANDS
  738. this.send_command(model_types_command).then(this.get_output)
  739. .then(function(data){
  740. console.log("model_types");
  741. console.log(data);
  742. model_types = data;
  743. })
  744. .then(this.send_command(model_modify)).then(this.get_output)
  745. .then(function(data){
  746. console.log("model_modify");
  747. console.log(data);
  748. })
  749. .then(this.send_command(model_dump)).then(this.get_output)
  750. .then(function(data){
  751. data = data.replace("Success: ", "");
  752. let AS = eval(JSON.parse(data));
  753. ModelVerseConnector.load_MV_model(model_types, AS)
  754. })
  755. .then(function () {
  756. ModelVerseConnector.set_status(ModelVerseConnector.OKAY);
  757. })
  758. .catch(
  759. function (err) {
  760. console.log("Error with model loading!");
  761. console.log(err);
  762. ModelVerseConnector.set_status(ModelVerseConnector.ERROR);
  763. }
  764. );
  765. }
  766. /*********END WRAPPER FUNCTIONS**********/
  767. }