exportmtomd.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. const {
  2. __errorContinuable,
  3. __httpReq,
  4. __wHttpReq,
  5. __postInternalErrorMsg, __postMessage,
  6. __sequenceNumber,
  7. __successContinuable,
  8. __uri_to_id
  9. } = require("../__worker");
  10. const _do = require("../___do");
  11. const _utils = require('../utils');
  12. const _fs = _do.convert(require('fs'), ['readFile', 'writeFile', 'readdir']);
  13. const _fspp = _do.convert(require('../___fs++'), ['mkdirs']);
  14. module.exports = {
  15. 'interfaces': [{'method':'POST', 'url=':'/exportmtomd'}],
  16. 'csworker':
  17. function(resp, method, uri, reqData, wcontext) {
  18. var actions = [__wHttpReq('GET', '/current.model?wid=' + wcontext.__aswid)];
  19. _do.chain(actions) (
  20. function(asdata) {
  21. var writeActions = [_fspp.mkdirs('./exported_to_md/')];
  22. _do.chain(writeActions) (
  23. function() {
  24. var file_contents = '';
  25. var as = _utils.jsonp(asdata['data']);
  26. var mms = as['metamodels'];
  27. /*
  28. R: If a pattern metamodel is found: add the original metamodel to the imports list (if not already present)
  29. e.g. rpg.pattern --> rpg
  30. */
  31. var mmsToAdd = [];
  32. for (var i in mms) {
  33. var mm = mms[i];
  34. var pos = mm.search(".pattern");
  35. if (pos != -1) {
  36. var mmToAdd = mm.replace(".pattern", "");
  37. if (mms.indexOf(mmToAdd) == -1) {
  38. mms.push(mmToAdd);
  39. }
  40. }
  41. }
  42. /*
  43. R: Start variable name fixing
  44. */
  45. var reservedWordsPattern = /(Sequence|Model|)/g;
  46. var stringEscapingPattern = /\\/g;
  47. // A word character is a character from a-z, A-Z, 0-9, including the _ (underscore) character.
  48. var nonWordCharPattern = /\W/g;
  49. var reservedWordsPattern = /(Sequence|Model|Edge|Node)/;
  50. var escapes = [[/\//g, "\\\/"], [/\\/g, "\\\\"], [/\"/g, "\\\""]];
  51. var nonWordCharPattern = /\W/g; // A word character is a character from a-z, A-Z, 0-9, including the _ (underscore) character.
  52. function fixName(name) {
  53. name = name.replace(nonWordCharPattern, '_');
  54. var matchArr = name.match(reservedWordsPattern);
  55. if (matchArr != null) {
  56. name = name.replace(matchArr[0], matchArr[0] + '0');
  57. }
  58. return name;
  59. }
  60. function escapeString(str) {
  61. for (i in escapes) {
  62. str = str.replace(escapes[i][0], escapes[i][1]);
  63. }
  64. return str;
  65. }
  66. for (var key in as.nodes) {
  67. // All names of Nodes
  68. var node = as.nodes[key];
  69. // console.log(node.$type);
  70. // console.log(node);
  71. if (node['$type'] != null) { // Fix node name
  72. parts = node['$type'].split('/');
  73. node['$type'] = parts.join('/').replace(parts[parts.length - 1], fixName(parts[parts.length - 1]));
  74. }
  75. for (var prop in node) {
  76. if (prop != '$type') {
  77. // All names and values of properties
  78. if (node[prop]['type'] == 'string' | node[prop]['type'] == 'code')
  79. node[prop]['value'] = escapeString(node[prop]['value']);
  80. }
  81. }
  82. }
  83. /*
  84. R: End variable name fixing
  85. */
  86. extract_md_type = function(mm) {
  87. mm_parts = mm.split('/');
  88. return fixName(mm_parts[mm_parts.length - 1]); // R: Add fixName() here to apply it to types as well
  89. };
  90. // Import extra metamodels
  91. for (var i = mms.length - 1; i >= 0; i--) {
  92. file_contents += 'load "' + extract_md_type(mms[i]) + '"\n';
  93. }
  94. // FIX: Define an auxiliary metamodel which imports all other metamodels and is then instantiated by the main model
  95. var mm = extract_md_type(mms[0]);
  96. var modelName = reqData['name'];
  97. mm = 'Metamodel';
  98. file_contents += '\nModel ' + mm + ' imports ';
  99. for (var i = 0; i < mms.length - 1; i++) {
  100. file_contents += extract_md_type(mms[i]) + ', ';
  101. }
  102. file_contents += extract_md_type(mms[mms.length - 1]);
  103. file_contents += ' {} \n\n';
  104. var edges = {};
  105. for (var i = 0; i < as.edges.length; i += 2) {
  106. if (as.edges[i].dest != as.edges[i + 1].src) console.error('The source and destination of the edge are different!');
  107. edges[as.edges[i].dest] = ([as.edges[i].src, as.edges[i + 1].dest]);
  108. }
  109. // Model definition
  110. file_contents += mm + ' ' + modelName + ' {\n';
  111. // console.log('------------');
  112. // console.log(as.nodes);
  113. // console.log('------------');
  114. // console.log(as.edges);
  115. // console.log('------------');
  116. for (var key in as.nodes) {
  117. var node = as.nodes[key];
  118. // console.log('-----start-----');
  119. // console.log(node);
  120. var node_type = extract_md_type(node['$type']);
  121. file_contents += node_type + ' ' + node_type + '_' + key;
  122. file_contents += ' {\n';
  123. if (key in edges) {
  124. file_contents += 'src = ' + extract_md_type(as.nodes[edges[key][0]]['$type']) + '_' + edges[key][0] +';\n';
  125. file_contents += 'dst = ' + extract_md_type(as.nodes[edges[key][1]]['$type']) + '_' + edges[key][1] +';\n';
  126. }
  127. // var incoming = [];
  128. // var outgoing = [];
  129. // for (var e in edges) {
  130. // if (edges[e][0] == key) {
  131. // outgoing.push(e);
  132. // }
  133. // if (edges[e][1] == key) {
  134. // incoming.push(e);
  135. // }
  136. // }
  137. // if (incoming.length) {
  138. // file_contents +=
  139. // incoming.map(function(key) {
  140. // var edge = edges[key];
  141. // var srcKey = edge[0];
  142. // var attr = 'in' + extract_md_type(as.nodes[key]['$type']);
  143. // var type = extract_md_type(as.nodes[srcKey]['$type']);
  144. // var name = type + '_' + srcKey;
  145. // return attr + ' = ' + name + ';';
  146. // }).join('\n') + '\n'
  147. // ;
  148. // }
  149. // if (outgoing.length) {
  150. // file_contents +=
  151. // outgoing.map(function(key) {
  152. // var edge = edges[key];
  153. // var destKey = edge[1];
  154. // var attr = 'out' + extract_md_type(as.nodes[key]['$type']);
  155. // var type = extract_md_type(as.nodes[destKey]['$type']);
  156. // var name = type + '_' + destKey;
  157. // return attr + ' = ' + name + ';';
  158. // }).join('\n') + '\n'
  159. // ;
  160. // }
  161. for (var prop in node) {
  162. if (prop != '$type') {
  163. var pre = '';
  164. var post = '';
  165. if (node[prop]['type'] == 'string' | node[prop]['type'] == 'code') {
  166. pre = '"';
  167. post = '"';
  168. } else if (node[prop]['type'].search('list') >= 0) {
  169. pre = '[';
  170. post = ']';
  171. }
  172. // fixName should be extracted from here and done at the start
  173. file_contents += fixName(prop) + ' = ' + pre + node[prop]['value'] + post + ';\n';
  174. }
  175. }
  176. file_contents += '}\n';
  177. // }
  178. }
  179. file_contents += '}\n';
  180. _fs.writeFileSync('./exported_to_md/' + reqData['name'] + '.mdepth', file_contents);
  181. __postMessage({ 'statusCode': 200,
  182. 'respIndex': resp});
  183. },
  184. function(writeErr) {__postInternalErrorMsg(resp, writeErr);}
  185. );
  186. },
  187. function(err) {__postInternalErrorMsg(resp, err);}
  188. );
  189. },
  190. 'asworker':
  191. function(resp, method, uri, reqData, wcontext)
  192. {
  193. __postMessage(
  194. {'statusCode': 200,
  195. 'respIndex': resp});
  196. }
  197. };