query_response.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /* This file is part of AToMPM - A Tool for Multi-Paradigm Modelling
  2. * Copyright 2011 by the AToMPM team and licensed under the LGPL
  3. * See COPYING.lesser and README.md in the root of this project for full details
  4. */
  5. var __nextASWSequenceNumber = '/asworker#1',
  6. __nextCSWSequenceNumber = '/csworker#1',
  7. __pendingASWChangelogs = [],
  8. __pendingCSWChangelogs = [];
  9. /* delete pending changelogs older than the specified sequence number */
  10. function __clearObsoleteChangelogs(pendingChangelogs,sn)
  11. {
  12. pendingChangelogs =
  13. pendingChangelogs.filter(
  14. function(c)
  15. {
  16. return utils.sn2int(pc['sequence#']) > utils.sn2int(sn);
  17. });
  18. }
  19. /* set the value of __nextASWSequenceNumber to the given sequence number */
  20. function __forceNextASWSequenceNumber(sn)
  21. {
  22. __nextASWSequenceNumber = sn;
  23. __clearObsoleteChangelogs(__pendingASWChangelogs,sn);
  24. }
  25. /* set the value of __nextCSWSequenceNumber to the given sequence number */
  26. function __forceNextCSWSequenceNumber(sn)
  27. {
  28. __nextCSWSequenceNumber = sn;
  29. __clearObsoleteChangelogs(__pendingCSWChangelogs,sn);
  30. }
  31. //Todo: Shred this into smaller functions
  32. /* apply a changelog (or postpone its application)
  33. 0. check the changelog's sequence number to know if we should handle it
  34. now or later... note that we will be receiving changelogs with both
  35. asworker and csworker sequence numbers
  36. 1. iterate through and handle the changelog's steps
  37. 2. apply next pending changelog, if any and if applicable */
  38. function __handleChangelog(changelog,seqNum,hitchhiker)
  39. {
  40. console.debug(' ++ ('+seqNum+') ',changelog);
  41. var isCSWChangelog = seqNum.match(/csworker/);
  42. nextSeqNum =
  43. (isCSWChangelog ? __nextCSWSequenceNumber : __nextASWSequenceNumber),
  44. pendingChangelogs =
  45. (isCSWChangelog ? __pendingCSWChangelogs : __pendingASWChangelogs);
  46. if( utils.sn2int(seqNum) > utils.sn2int(nextSeqNum) )
  47. {
  48. pendingChangelogs.push(
  49. {'changelog':changelog,
  50. 'sequence#':seqNum,
  51. 'hitchhiker':hitchhiker});
  52. pendingChangelogs.sort(
  53. function(a,b)
  54. {
  55. return utils.sn2int(a['sequence#']) - utils.sn2int(b['sequence#']);
  56. });
  57. return;
  58. }
  59. else if( utils.sn2int(seqNum) < utils.sn2int(nextSeqNum) )
  60. {
  61. WindowManagement.openDialog(
  62. __FATAL_ERROR,
  63. 'invalid changelog sequence# :: '+utils.sn2int(seqNum));
  64. return;
  65. }
  66. WindowManagement.setWindowTitle(true);
  67. changelog.forEach(
  68. function(step)
  69. {
  70. if( (step['op'] == 'RMNODE' ||
  71. step['op'] == 'RMEDGE' ||
  72. step['op'] == 'CHATTR') &&
  73. __watching(step['id']) )
  74. {
  75. console.warn(
  76. 'someone has altered the node you are currently editing...'+
  77. 'to keep your changes, click OK... to discard them and see'+
  78. ' what has changed, click CANCEL');
  79. __changed(step['id'],true);
  80. }
  81. if( step['op'] == 'MKEDGE' )
  82. ;
  83. /* react to the removal of an edge */
  84. else if( step['op'] == 'RMEDGE' )
  85. {
  86. __removeEdge(
  87. step['id1']+'--'+step['id2'],
  88. [step['id1'],step['id2']]);
  89. if( __selection != undefined )
  90. __select( utils.filter(__selection['items'],[edgeId]) );
  91. }
  92. /* react to the creation of a node */
  93. else if( step['op'] == 'MKNODE' )
  94. {
  95. var node = utils.jsonp(step['node']),
  96. icon = __createIcon(node,step['id']);
  97. if( '$segments' in node )
  98. {
  99. var linkStyle = node['link-style']['value'],
  100. segments = node['$segments']['value'];
  101. icon.setAttr('__segments',utils.jsons(segments));
  102. for( var edgeId in segments )
  103. __createEdge(segments[edgeId], linkStyle, edgeId, step['id']);
  104. }
  105. }
  106. /* react to the removal of a node */
  107. else if( step['op'] == 'RMNODE' )
  108. {
  109. __icons[step['id']]['icon'].remove();
  110. __icons[step['id']]['edgesOut'].forEach(__removeEdge);
  111. __icons[step['id']]['edgesIn'].forEach(__removeEdge);
  112. delete __icons[step['id']];
  113. if( __selection != undefined )
  114. __select( utils.filter(__selection['items'],[step['id']]) );
  115. }
  116. /* react to attribute update
  117. CASE 1 : Icon/Link layout attribute (position, etc.)
  118. update the corresponding attribute of the corresponding icon
  119. in __icons + actually effect the layout transformation (via
  120. __setIconTransform())
  121. CASE 2 : Link attribute ($segments / link-style)
  122. redraw existing edges and create any new ones
  123. CASE 3 : VisualObject attribute update
  124. update the corresponding attribute of the corresponding icon's
  125. corresponding vobject */
  126. else if( step['op'] == 'CHATTR' )
  127. {
  128. /* CASE 1 */
  129. if(utils.contains(['position','orientation','scale'],step['attr']))
  130. {
  131. var newVal = step['new_val'],
  132. icon = __icons[step['id']]['icon'];
  133. /* bugfix where newVal would get a string instead of the array of values
  134. should search for reason why it has string in the first place - Vasco - 02-02-2017*/
  135. if( typeof newVal == 'string'){
  136. newVal = newVal.replace('[','');
  137. newVal = newVal.replace(']','');
  138. newVal = newVal.split(',');
  139. }
  140. /* endbugfix*/
  141. if( step['attr'] == 'position' )
  142. {
  143. var bbox = icon.getBBox();
  144. icon.setAttr('__x', __getAbsoluteCoordinate(newVal[0],bbox.width) );
  145. icon.setAttr('__y', __getAbsoluteCoordinate(newVal[1],bbox.height) );
  146. }
  147. else if( step['attr'] == 'orientation' )
  148. icon.setAttr('__r',newVal);
  149. else if( step['attr'] == 'scale' )
  150. {
  151. icon.setAttr('__sx',newVal[0]);
  152. icon.setAttr('__sy',newVal[1]);
  153. }
  154. __setIconTransform(step['id']);
  155. }
  156. /* CASE 2 */
  157. else if(utils.contains(['$segments','link-style','arrowTail','arrowHead'],step['attr']))
  158. {
  159. var icon = __icons[step['id']]['icon'],
  160. segments,
  161. linkStyle;
  162. if( step['attr'] == '$segments' )
  163. {
  164. segments = step['new_val'];
  165. linkStyle = utils.jsonp(icon.getAttr('__linkStyle'));
  166. icon.setAttr('__segments',utils.jsons(segments));
  167. }
  168. else if (step['attr'] == 'link-style')
  169. {
  170. segments = utils.jsonp(icon.getAttr('__segments'));
  171. linkStyle = step['new_val'];
  172. icon.setAttr('__linkStyle',utils.jsons(linkStyle));
  173. }
  174. else
  175. {
  176. segments = utils.jsonp(icon.getAttr('__segments'));
  177. linkStyle = utils.jsonp(icon.getAttr('__linkStyle'));
  178. }
  179. for( var edgeId in segments )
  180. if( edgeId in __edges )
  181. __redrawEdge(edgeId,segments[edgeId],linkStyle);
  182. else
  183. /* react to the creation of an edge */
  184. __createEdge(
  185. segments[edgeId], linkStyle, edgeId, step['id']);
  186. }
  187. /* CASE 3
  188. NOTE:: certain VisualObject parameters need some special care...
  189. a) position, orientation, scale: these can only be changed by
  190. the csworker layout constraint solver and link decorator
  191. positioner... after each change, the transformation applied
  192. to the vobject is overwritten
  193. b) r/rx/ry: changing these causes relevant shapes to grow
  194. around their center thereby changing their top-left corner
  195. ... we translate the said shapes to compensate
  196. c) Polygons/Stars: see __editPolygon/Star(..)
  197. d) style: pass {...,attr:val,...} hash directly to attr(..)
  198. e) src: make sure URL is valid / make it valid
  199. f) Text VisualObject: see __valignText(..) */
  200. else
  201. {
  202. var matches = step['attr'].match(/.*\/(.*)\/(.*)/),
  203. vid = matches[1],
  204. vobj = __icons[step['id']]['vobjects'][vid],
  205. attr = matches[2];
  206. if(utils.contains(['position','scale','orientation'],attr))
  207. {
  208. var newVal = (utils.isArray(step['new_val']) ?
  209. [__getVobjGeomAttrVal(step['new_val'][0]).latest,
  210. __getVobjGeomAttrVal(step['new_val'][1]).latest] :
  211. parseFloat(
  212. __getVobjGeomAttrVal(step['new_val']).latest) );
  213. if( attr == 'position' )
  214. {
  215. vobj.node.setAttribute('__x',
  216. utils.buildVobjGeomAttrVal(
  217. vobj.node.getAttribute('__x'), newVal[0]) );
  218. vobj.node.setAttribute('__y',
  219. utils.buildVobjGeomAttrVal(
  220. vobj.node.getAttribute('__y'), newVal[1]) );
  221. }
  222. else if( attr == 'scale' )
  223. {
  224. var sx = vobj.node.getAttribute('__sx'),
  225. sy = vobj.node.getAttribute('__sy');
  226. vobj.node.setAttribute('__sx',
  227. utils.buildVobjGeomAttrVal(
  228. sx, newVal[0]*__getVobjGeomAttrVal(sx).initial) );
  229. vobj.node.setAttribute('__sy',
  230. utils.buildVobjGeomAttrVal(
  231. sy, newVal[1]*__getVobjGeomAttrVal(sy).initial) );
  232. }
  233. else
  234. {
  235. var r = vobj.node.getAttribute('__r');
  236. vobj.node.setAttribute('__r',
  237. utils.buildVobjGeomAttrVal(
  238. r, newVal+__getVobjGeomAttrVal(r).initial) );
  239. }
  240. __setVobjectTransform(vobj);
  241. }
  242. if(utils.contains(['r','rx','ry'],attr))
  243. {
  244. var oldVal = vobj.attr(attr) || vobj.node.getAttribute('__'+attr);
  245. offset = step['new_val'] - oldVal;
  246. vobj.translate(
  247. utils.contains(['r','rx'],attr) ? offset : 0,
  248. utils.contains(['r','ry'],attr) ? offset : 0);
  249. }
  250. if( step['id'].match(/\/PolygonIcon\//) &&
  251. utils.contains(['r','sides'],attr) )
  252. __editPolygon(vobj,attr,step['new_val']);
  253. else if( step['id'].match(/\/StarIcon\//) &&
  254. utils.contains(['r','rays'],attr) )
  255. __editStar(vobj,attr,step['new_val']);
  256. try {var newVal = utils.jsonp(step['new_val']);}
  257. catch(err) {var newVal = step['new_val'];}
  258. if( attr == 'style' )
  259. vobj.attr( newVal );
  260. else if( attr == 'src' )
  261. vobj.attr( 'src', __relativizeURL(newVal) );
  262. else
  263. vobj.attr( __ATTR_MAP[attr] || attr, newVal );
  264. if( vobj.type == 'text' )
  265. __valignText(vobj);
  266. }
  267. if( __isSelected(step['id']) )
  268. utils.doAfterUnlessRepeated(
  269. function(selection) {
  270. __select(selection);
  271. }, [__selection['items']], 5
  272. );
  273. }
  274. /* react to loading of an IconDefinition (CS metamodel)
  275. 1. setup and show appropriate toolbar
  276. 2. replace default toolbar button icons by icons described in
  277. the loaded metamodel */
  278. else if( step['op'] == 'LOADMM' )
  279. {
  280. var data = eval('('+step['mm']+')');
  281. GUIUtils.setupAndShowToolbar(
  282. step['name']+'.metamodel',
  283. data,
  284. __METAMODEL_TOOLBAR);
  285. for( var t in data.types )
  286. {
  287. if( t.match(/(.*)Link$/) )
  288. continue;
  289. else if( ! GUIUtils.$$(step['name']+'.metamodel/'+t) )
  290. {
  291. if( !t.match(/(.*)Icon$/) )
  292. console.error('Icon typenames must be "<AbstractType>Icon", the following does not conform :: '+t);
  293. else
  294. console.error('found icon definition for unknwon abstract type :: '+t);
  295. continue;
  296. }
  297. var im =
  298. data.types[t].filter(
  299. function(attr)
  300. {
  301. return attr['name'] == '$contents';
  302. })[0]['default'];
  303. CompileUtils.compileAndDrawIconModel(
  304. im,
  305. Raphael(GUIUtils.$$(step['name']+'.metamodel/'+t)),
  306. {'size':__ICON_SIZE,
  307. 'wrap':true});
  308. GUIUtils.$$(step['name']+'.metamodel/'+t).removeChild(
  309. GUIUtils.$$(step['name']+'.metamodel/'+t).lastChild );
  310. }
  311. }
  312. else if( step['op'] == 'LOADASMM' )
  313. __loadedToolbars[step['name']+'.metamodel'] =
  314. eval('('+step['mm']+')');
  315. else if( step['op'] == 'DUMPMM' )
  316. {
  317. var csmmPath = step['name']+'.metamodel';
  318. GUIUtils.removeToolbar(csmmPath);
  319. }
  320. else if( step['op'] == 'RESETM' )
  321. {
  322. var m = utils.jsonp(step['new_model']);
  323. GUIUtils.resetCanvas();
  324. for( var id in m.nodes )
  325. {
  326. var node = m.nodes[id],
  327. icon = __createIcon(node,id);
  328. if( '$segments' in node )
  329. {
  330. var linkStyle = node['link-style']['value'],
  331. segments = node['$segments']['value'];
  332. icon.setAttr('__segments',utils.jsons(segments));
  333. for( var edgeId in segments )
  334. __createEdge( segments[edgeId], linkStyle, edgeId, id);
  335. }
  336. }
  337. WindowManagement.setWindowTitle(false);
  338. }
  339. else if( step['op'] == 'SYSOUT' )
  340. {
  341. if( step['text'].match(/^ERROR :: /) )
  342. console.error(step['text']);
  343. else if( step['text'].match(/^WARNING :: /) )
  344. console.warn(step['text']);
  345. else if( step['text'].match(/^CLIENT_BDAPI :: /) )
  346. {
  347. var op = utils.jsonp(step['text'].match(/^CLIENT_BDAPI :: (.*)/)[1]);
  348. this[op['func']](op['args']);
  349. }
  350. else
  351. console.log('MESSAGE :: '+step['text']);
  352. }
  353. ///////
  354. else if (step['op'] == 'CHAT')
  355. {
  356. Collaboration.updateChat(step['text']);
  357. }
  358. });
  359. if( isCSWChangelog )
  360. nextSeqNum = __nextCSWSequenceNumber =
  361. utils.incrementSequenceNumber(nextSeqNum);
  362. else
  363. nextSeqNum = __nextASWSequenceNumber =
  364. utils.incrementSequenceNumber(nextSeqNum);
  365. if( pendingChangelogs.length > 0 &&
  366. nextSeqNum == pendingChangelogs[0]['sequence#'] )
  367. {
  368. var pc = pendingChangelogs.shift();
  369. __handleChangelog(
  370. pc['changelog'],
  371. pc['sequence#'],
  372. pc['hitchhiker']);
  373. }
  374. }