Browse Source

Merge branch 'master' of bentley/AToMPM into bentleyscommits

simon 6 years ago
parent
commit
6c7401fa1e

+ 1 - 0
README.md

@@ -19,6 +19,7 @@ To install AToMPM, follow these steps:
         * For Python2: `pip install six`
         * For Python2: `pip install six`
         * For Python3: `pip3 install six`
         * For Python3: `pip3 install six`
 * Download and install node.js
 * Download and install node.js
+    * Required version: >= 8.0
     * Use a package manager on Linux
     * Use a package manager on Linux
     * Or visit https://nodejs.org/en/download/
     * Or visit https://nodejs.org/en/download/
 * Download and unzip the source files for the newest AToMPM release from https://msdl.uantwerpen.be/git/simon/AToMPM/releases
 * Download and unzip the source files for the newest AToMPM release from https://msdl.uantwerpen.be/git/simon/AToMPM/releases

+ 68 - 60
___fs++.js

@@ -9,8 +9,8 @@
   	provide higher-level functions that those provided by nodejs' fs module */
   	provide higher-level functions that those provided by nodejs' fs module */
 
 
 var _cp = require('child_process'),
 var _cp = require('child_process'),
-	 _os = require('os'),
-     _fs = require('fs');
+	_os = require('os'),
+	_fs = require('fs');
 
 
 
 
 /* NOTE:: because microsoft has apparently diversified into hiring comedians,
 /* NOTE:: because microsoft has apparently diversified into hiring comedians,
@@ -18,6 +18,10 @@ var _cp = require('child_process'),
 exports.cp =
 exports.cp =
 	function(src,dest,callback)
 	function(src,dest,callback)
 	{
 	{
+		//guard against injection
+		src = src.split(';')[0];
+		dest = dest.split(';')[0];
+
 		switch(_os.type())
 		switch(_os.type())
 		{
 		{
 			case 'Windows_NT' :
 			case 'Windows_NT' :
@@ -30,7 +34,7 @@ exports.cp =
 							callback(err,stdout,stderr);
 							callback(err,stdout,stderr);
 					});
 					});
 				break;
 				break;
-				
+
 			case 'Linux'  :
 			case 'Linux'  :
 			case 'Darwin' :
 			case 'Darwin' :
 				_cp.exec('cp -R "'+src+'" "'+dest+'"',callback);
 				_cp.exec('cp -R "'+src+'" "'+dest+'"',callback);
@@ -51,6 +55,9 @@ exports.cp =
 exports.findfiles =
 exports.findfiles =
 	function(dir,callback)
 	function(dir,callback)
 	{
 	{
+		//guard against injection
+		dir = dir.split(';')[0];
+
 		switch(_os.type())
 		switch(_os.type())
 		{
 		{
 			case 'Windows_NT' :
 			case 'Windows_NT' :
@@ -61,27 +68,30 @@ exports.findfiles =
 							callback(err,stdout,stderr);
 							callback(err,stdout,stderr);
 						else
 						else
 						{
 						{
-							var windir = (dir.charAt(0)=='.' ? dir.substring(1) : dir).
-												replace(/\//g,'\\'),
-								 paths  = stdout.split('\r\n').map(
+							let windir = (dir.charAt(0)=='.' ? dir.substring(1) : dir).
+								replace(/\//g,'\\'),
+								paths  = stdout.split('\r\n').map(
 									function(path)
 									function(path)
 									{
 									{
-										var newpath = dir+path.substring(
-														path.indexOf(windir)+windir.length).
-													  replace(/\\/g,'/');
-                                        try {
-                                            if (_fs.lstatSync(path).isDirectory()) {
-                                                newpath = newpath + '/';
-                                            }
-                                        } catch (e) {}
-                                        return newpath;
+										let newpath = dir+path.substring(
+											path.indexOf(windir)+windir.length).
+										replace(/\\/g,'/');
+										try {
+											if (_fs.lstatSync(path).isDirectory()) {
+												newpath = newpath + '/';
+											}
+										} catch (e) {
+											//console.log("Error!");
+											//console.log(e);
+										}
+										return newpath;
 									});
 									});
 							paths.pop();
 							paths.pop();
 							callback(err,paths.join('\n'),stderr);
 							callback(err,paths.join('\n'),stderr);
 						}
 						}
 					});
 					});
 				break;
 				break;
-				
+
 			case 'Linux'  :
 			case 'Linux'  :
 			case 'Darwin' :
 			case 'Darwin' :
 				_cp.exec('find "'+dir+'"',
 				_cp.exec('find "'+dir+'"',
@@ -90,14 +100,14 @@ exports.findfiles =
 						if( err )
 						if( err )
 							callback(err,stdout,stderr);
 							callback(err,stdout,stderr);
 						else {
 						else {
-                            var paths = stdout.slice(0,-1),
-                                newpaths = paths.split('\n').map(function(path) {
-                                    if (_fs.lstatSync(path).isDirectory()) {
-                                        return path + "/";
-                                    } else return path;
-                                });
+							let paths = stdout.slice(0,-1),
+								newpaths = paths.split('\n').map(function(path) {
+									if (_fs.lstatSync(path).isDirectory()) {
+										return path + "/";
+									} else return path;
+								});
 							callback(err,newpaths.join('\n'),stderr);
 							callback(err,newpaths.join('\n'),stderr);
-                        }
+						}
 					});
 					});
 				break;
 				break;
 
 
@@ -113,15 +123,18 @@ exports.findfiles =
 exports.mkdirs =
 exports.mkdirs =
 	function(dir,callback)
 	function(dir,callback)
 	{
 	{
-        var split_dir = dir.split('/'),
-            curr_dir = '';
-        for (var i in split_dir) {
-            curr_dir += split_dir[i] + '/';
-            if (!_fs.existsSync(curr_dir)) {
-                _fs.mkdir(curr_dir, 484, function(err) {if (err) {if (err.code != 'EEXIST') callback(err);}});
-            }
-        }
-        callback();
+		//guard against injection
+		dir = dir.split(';')[0];
+
+		let split_dir = dir.split('/'),
+			curr_dir = '';
+		for (let i in split_dir) {
+			curr_dir += split_dir[i] + '/';
+			if (!_fs.existsSync(curr_dir)) {
+				_fs.mkdir(curr_dir, 484, function(err) {if (err) {if (err.code != 'EEXIST') callback(err);}});
+			}
+		}
+		callback();
 	};
 	};
 
 
 
 
@@ -129,8 +142,12 @@ exports.mkdirs =
 exports.mv =
 exports.mv =
 	function(src,dest,callback)
 	function(src,dest,callback)
 	{
 	{
-        var split_string = src.split('/');
-        _fs.rename(src, dest + split_string[split_string.length-1],callback);
+		//guard against injection
+		src = src.split(';')[0];
+		dest = dest.split(';')[0];
+
+		let split_string = src.split('/');
+		_fs.rename(src, dest + split_string[split_string.length-1],callback);
 	};
 	};
 
 
 
 
@@ -138,37 +155,28 @@ exports.mv =
 exports.rmdirs =
 exports.rmdirs =
 	function(dir,callback)
 	function(dir,callback)
 	{
 	{
-		switch(_os.type())
-		{
-			case 'Windows_NT' :
-				_cp.exec('rmdir /s "'+dir+'"',callback);
-				break;
-				
-			case 'Linux'  :
-			case 'Darwin' :
-				_cp.exec('rm -rf "'+dir+'"',callback);
-				break;
+		//guard against injection
+		dir = dir.split(';')[0];
 
 
-			default:
-				throw 'unsupported OS :: '+_os.type();
-		}
+		_fs.rmdir(dir, callback)
 	};
 	};
 
 
-
-
 // http://stackoverflow.com/questions/18052762/remove-directory-which-is-not-empty
 // http://stackoverflow.com/questions/18052762/remove-directory-which-is-not-empty
 exports.deleteFolderRecursive = function(path) {
 exports.deleteFolderRecursive = function(path) {
-   if( _fs.existsSync(path) ) {
-       _fs.readdirSync(path).forEach(function(file,index){
-           var curPath = path + "/" + file;
-           if(_fs.lstatSync(curPath).isDirectory()) { // recurse
-               exports.deleteFolderRecursive(curPath);
-           } else { // delete file
-               _fs.unlinkSync(curPath);
-           }
-       });
-       _fs.rmdirSync(path);
-   }
+	//guard against injection
+	path = path.split(';')[0];
+
+	if( _fs.existsSync(path) ) {
+		_fs.readdirSync(path).forEach(function(file,index){
+			let curPath = path + "/" + file;
+			if(_fs.lstatSync(curPath).isDirectory()) { // recurse
+				exports.deleteFolderRecursive(curPath);
+			} else { // delete file
+				_fs.unlinkSync(curPath);
+			}
+		});
+		_fs.rmdirSync(path);
+	}
 };
 };
 	
 	
 	
 	

+ 0 - 1
client/atompm.html

@@ -42,7 +42,6 @@
 		<script text="text/javascript" src="client/connection_utils.js"></script>
 		<script text="text/javascript" src="client/connection_utils.js"></script>
 		<script text="text/javascript" src="client/window_management.js"></script>
 		<script text="text/javascript" src="client/window_management.js"></script>
 		<script text="text/javascript" src="client/file_browser.js"></script>
 		<script text="text/javascript" src="client/file_browser.js"></script>
-        <script text="text/javascript" src="client/modelverse_connector.js"></script>
 		<script text="text/javascript" src="client/query_response.js"></script>
 		<script text="text/javascript" src="client/query_response.js"></script>
 		<script text="text/javascript" src="client/collaboration.js"></script>
 		<script text="text/javascript" src="client/collaboration.js"></script>
 		<script text="text/javascript" src="client/layout.js"></script>
 		<script text="text/javascript" src="client/layout.js"></script>

+ 1 - 1
client/constants.js

@@ -7,7 +7,7 @@
 var __WEBPAGE__ = 'https://atompm.github.io/',
 var __WEBPAGE__ = 'https://atompm.github.io/',
 	__RELEASE_LOC__ = "https://api.github.com/repos/AToMPM/atompm/releases/latest",
 	__RELEASE_LOC__ = "https://api.github.com/repos/AToMPM/atompm/releases/latest",
 	__DOC_WEBPAGE__ = "https://msdl.uantwerpen.be/documentation/AToMPM/index.html",
 	__DOC_WEBPAGE__ = "https://msdl.uantwerpen.be/documentation/AToMPM/index.html",
-    __VERSION__ = '0.8.1',
+    __VERSION__ = '0.8.2',
     __DEFAULT_SAVEAS		 	= '.autosave.model',
     __DEFAULT_SAVEAS		 	= '.autosave.model',
 	 __TITLE						= 'AToMPM',
 	 __TITLE						= 'AToMPM',
 	 __EXITWARNING				= 'There are unsaved changes. Proceeding will cause'+
 	 __EXITWARNING				= 'There are unsaved changes. Proceeding will cause'+

+ 1 - 4
client/file_browser.js

@@ -294,7 +294,6 @@ class FileBrowser{
 
 
                     //fnames might be a function that returns the files in
                     //fnames might be a function that returns the files in
                     //the folder
                     //the folder
-                    //bentley: the ModelVerse only examines one folder at a time
                     let file_list = fnames;
                     let file_list = fnames;
                     if (!(Array.isArray(fnames))){
                     if (!(Array.isArray(fnames))){
                         file_list = await fnames(folder);
                         file_list = await fnames(folder);
@@ -399,9 +398,7 @@ class FileBrowser{
                     currfolder = folder;
                     currfolder = folder;
                 };
                 };
 
 
-        let file_browser_width = 120;
-        fileb.css("width", file_browser_width + 'ex')
-            .css("maxWidth", '100%');
+        fileb.css("maxWidth", '100%');
 
 
         navdiv.css("align", 'left');
         navdiv.css("align", 'left');
 
 

File diff suppressed because it is too large
+ 0 - 1074
client/modelverse_connector.js


+ 0 - 333
client/modelverse_connector_rendering.js

@@ -1,333 +0,0 @@
-/* This file holds the code for rendering SimpleClassDiagrams from the ModelVerse.
-
-1) The rendering meta-model and transformation are sent to the ModelVerse.
-2) The transformation executes, creating the rendered model and returning the JSON.
-3) 'model_CS' will then contain the rendered concrete syntax
-
-This method is dependent on the meta-model being SimpleClassDiagrams.
-Therefore, this code should be put aside until a more robust rendering
-system in the ModelVerse is created.
-
-For example, it would be ideal to have a render transformation explicitly defined
-for each metamodel in the ModelVerse. Then the render_model command could just
-return the JSON for the rendered model (or just the updated portion).
-
- */
-
-class ModelVerseRenderer {
-
-    static get_CS(model_name) {
-
-        //get CS for model
-
-        let SCD = "formalisms/SimpleClassDiagrams";
-        let MM_render = "formalisms/SCD_graphical";
-        let render_trans_model = "models/render_SCD";
-        let render_MM = this.get_render_mm();
-        let render_trans_code = this.get_render_trans();
-        let render_model_add = {
-            'data': encodeURIComponent(utils.jsons(["model_add", SCD, MM_render, render_MM]))
-        };
-
-        let transformation_between = {
-            'data': encodeURIComponent(utils.jsons(["transformation_add_AL", "rendered", MM_render, "abstract", SCD, "", "rendered", MM_render, "", render_trans_model]))
-        };
-
-        let transformation_data = {
-            'data': encodeURIComponent(utils.jsons(["transformation_add_AL", render_trans_code]))
-        };
-
-        let model_rendered = {
-            'data': encodeURIComponent(utils.jsons(["model_render", model_name, render_trans_model, "models/rendered_model"]))
-        };
-
-        //CS COMMANDS
-
-        let model_CS = null;
-
-        //TODO: only need to add models if not present
-        ModelVerseConnector.send_command(render_model_add).then(ModelVerseConnector.get_output)
-            .then(ModelVerseConnector.send_command(transformation_between)).then(ModelVerseConnector.get_output)
-            .then(ModelVerseConnector.send_command({})).then(ModelVerseConnector.get_output)
-            .then(ModelVerseConnector.send_command(transformation_data)).then(ModelVerseConnector.get_output)
-            .then(ModelVerseConnector.send_command(model_rendered)).then(ModelVerseConnector.get_output)
-
-            .then(function(data){
-                // console.log("Data before: ");
-                // console.log(data);
-                data = data.replace("Success: ", "");
-                // console.log("Data after:");
-                // console.log(data);
-                model_CS = eval(JSON.parse(data));
-            });
-
-    }
-
-    static get_render_mm() {
-        let mm = "include \"primitives.alh\"\n" +
-            "\n" +
-            "SimpleAttribute Natural {}\n" +
-            "SimpleAttribute String {}\n" +
-            "SimpleAttribute Boolean {}\n" +
-            "\n" +
-            "Class GraphicalElement {\n" +
-            "    x : Natural\n" +
-            "    y : Natural\n" +
-            "    layer : Natural\n" +
-            "}\n" +
-            "\n" +
-            "Class Group : GraphicalElement {\n" +
-            "    __asid : String\n" +
-            "    dirty : Boolean\n" +
-            "}\n" +
-            "\n" +
-            "Association ConnectingLine (Group, Group) {\n" +
-            "    offsetSourceX : Natural\n" +
-            "    offsetSourceY : Natural\n" +
-            "    offsetTargetX : Natural\n" +
-            "    offsetTargetY : Natural\n" +
-            "    lineWidth : Natural\n" +
-            "    lineColour : String\n" +
-            "    arrow : Boolean\n" +
-            "    __asid : String\n" +
-            "    dirty : Boolean\n" +
-            "    layer : Natural\n" +
-            "}\n" +
-            "\n" +
-            "Class LineElement : GraphicalElement {\n" +
-            "    lineWidth : Natural\n" +
-            "    lineColour : String\n" +
-            "}\n" +
-            "\n" +
-            "Class Text : LineElement {\n" +
-            "    text : String\n" +
-            "}\n" +
-            "\n" +
-            "Class Line : LineElement {\n" +
-            "    targetX : Natural\n" +
-            "    targetY : Natural\n" +
-            "    arrow : Boolean\n" +
-            "}\n" +
-            "\n" +
-            "Class Shape : LineElement {\n" +
-            "    fillColour : String\n" +
-            "    width : Natural\n" +
-            "    height : Natural\n" +
-            "}\n" +
-            "\n" +
-            "Class Figure : GraphicalElement {\n" +
-            "    width : Natural\n" +
-            "    height : Natural\n" +
-            "}\n" +
-            "\n" +
-            "Class SVG {\n" +
-            "    data : String\n" +
-            "}\n" +
-            "\n" +
-            "Class Rectangle : Shape {\n" +
-            "}\n" +
-            "\n" +
-            "Class Ellipse : Shape {\n" +
-            "}\n" +
-            "\n" +
-            "Association contains (Group, GraphicalElement) {}\n" +
-            "Association renders (Figure, SVG) {\n" +
-            "    source_lower_cardinality = 1\n" +
-            "    target_lower_cardinality = 1\n" +
-            "    target_upper_cardinality = 1\n" +
-            "}"
-        ;
-
-        return mm;
-    }
-
-    static get_render_trans() {
-        let trans = "include \"primitives.alh\"\n" +
-            "include \"modelling.alh\"\n" +
-            "include \"object_operations.alh\"\n" +
-            "include \"utils.alh\"\n" +
-            "\n" +
-            "Boolean function main(model : Element):\n" +
-            "\tElement elements\n" +
-            "\tString class\n" +
-            "\tElement attrs\n" +
-            "\tElement attr_keys\n" +
-            "\tString attr_key\n" +
-            "\tString group\n" +
-            "\tString elem\n" +
-            "\tInteger loc\n" +
-            "\tInteger text_loc\n" +
-            "\tElement related_groups\n" +
-            "\tloc = 10\n" +
-            "\n" +
-            "\tElement groups\n" +
-            "\tgroups = dict_create()\n" +
-            "\n" +
-            "\telements = allInstances(model, \"rendered/Group\")\n" +
-            "\twhile (set_len(elements) > 0):\n" +
-            "\t\tgroup = set_pop(elements)\n" +
-            "\t\tif (set_len(allIncomingAssociationInstances(model, group, \"TracabilityClass\")) == 0):\n" +
-            "\t\t\tElement to_remove\n" +
-            "\t\t\tString elem_to_remove\n" +
-            "\t\t\tto_remove = allAssociationDestinations(model, group, \"rendered/contains\")\n" +
-            "\t\t\twhile (set_len(to_remove) > 0):\n" +
-            "\t\t\t\telem_to_remove = set_pop(to_remove)\n" +
-            "\t\t\t\tif (read_type(model, elem_to_remove) == \"rendered/Group\"):\n" +
-            "\t\t\t\t\tset_add(to_remove, elem_to_remove)\n" +
-            "\t\t\t\telse:\n" +
-            "\t\t\t\t\tmodel_delete_element(model, elem_to_remove)\n" +
-            "\t\t\tmodel_delete_element(model, group)\n" +
-            "\n" +
-            "\telements = allInstances(model, \"abstract/Class\")\n" +
-            "\twhile (set_len(elements) > 0):\n" +
-            "\t\tclass = set_pop(elements)\n" +
-            "\t\t\n" +
-            "\t\tInteger x\n" +
-            "\t\tInteger y\n" +
-            "\t\tx = loc\n" +
-            "\t\ty = 10\n" +
-            "\n" +
-            "\t\t// Check if there is already an associated element\n" +
-            "\t\tif (set_len(allOutgoingAssociationInstances(model, class, \"TracabilityClass\")) > 0):\n" +
-            "\t\t\t// Yes, but is it still clean?\n" +
-            "\t\t\tBoolean dirty\n" +
-            "\t\t\tdirty = False\n" +
-            "\n" +
-            "\t\t\trelated_groups = allAssociationDestinations(model, class, \"TracabilityClass\")\n" +
-            "\t\t\twhile (set_len(related_groups) > 0):\n" +
-            "\t\t\t\tgroup = set_pop(related_groups)\n" +
-            "\t\t\t\tif (value_eq(read_attribute(model, group, \"dirty\"), True)):\n" +
-            "\t\t\t\t\t// No, so mark all as dirty\n" +
-            "\t\t\t\t\tdirty = True\n" +
-            "\t\t\t\t\tbreak!\n" +
-            "\t\t\t\telse:\n" +
-            "\t\t\t\t\t// Yes, so just ignore this!\n" +
-            "\t\t\t\t\tcontinue!\n" +
-            "\n" +
-            "\t\t\tif (bool_not(dirty)):\n" +
-            "\t\t\t\tdict_add(groups, class, group)\n" +
-            "\t\t\t\tcontinue!\n" +
-            "\t\t\telse:\n" +
-            "\t\t\t\trelated_groups = allAssociationDestinations(model, class, \"TracabilityClass\")\n" +
-            "\t\t\t\tElement to_remove\n" +
-            "\t\t\t\tString elem_to_remove\n" +
-            "\t\t\t\twhile (set_len(related_groups) > 0):\n" +
-            "\t\t\t\t\tgroup = set_pop(related_groups)\n" +
-            "\t\t\t\t\tto_remove = allAssociationDestinations(model, group, \"rendered/contains\")\n" +
-            "\t\t\t\t\tx = create_value(read_attribute(model, group, \"x\"))\n" +
-            "\t\t\t\t\ty = create_value(read_attribute(model, group, \"y\"))\n" +
-            "\t\t\t\t\twhile (set_len(to_remove) > 0):\n" +
-            "\t\t\t\t\t\telem_to_remove = set_pop(to_remove)\n" +
-            "\t\t\t\t\t\tif (read_type(model, elem_to_remove) == \"rendered/Group\"):\n" +
-            "\t\t\t\t\t\t\tset_add(to_remove, elem_to_remove)\n" +
-            "\t\t\t\t\t\telse:\n" +
-            "\t\t\t\t\t\t\tmodel_delete_element(model, elem_to_remove)\n" +
-            "\t\t\t\t\tmodel_delete_element(model, group)\n" +
-            "\n" +
-            "\t\tattr_keys = dict_keys(getAttributeList(model, class))\n" +
-            "\t\ttext_loc = 5\n" +
-            "\n" +
-            "\t\tgroup = instantiate_node(model, \"rendered/Group\", \"\")\n" +
-            "\t\tinstantiate_attribute(model, group, \"x\", x)\n" +
-            "\t\tinstantiate_attribute(model, group, \"y\", y)\n" +
-            "\t\tinstantiate_attribute(model, group, \"__asid\", list_read(string_split_nr(class, \"/\", 1), 1))\n" +
-            "\t\tinstantiate_attribute(model, group, \"layer\", 0)\n" +
-            "\t\tdict_add(groups, class, group)\n" +
-            "\t\tloc = loc + 200\n" +
-            "\n" +
-            "\t\telem = instantiate_node(model, \"rendered/Rectangle\", \"\")\n" +
-            "\t\tinstantiate_attribute(model, elem, \"x\", 0)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"y\", 0)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"height\", 40 + set_len(getInstantiatableAttributes(model, class, \"abstract/AttributeLink\")) * 20)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"width\", 150)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"lineWidth\", 2) \n" +
-            "\t\tinstantiate_attribute(model, elem, \"lineColour\", \"black\")\n" +
-            "\t\tinstantiate_attribute(model, elem, \"fillColour\", \"white\")\n" +
-            "\t\tinstantiate_attribute(model, elem, \"layer\", 1)\n" +
-            "\t\tinstantiate_link(model, \"rendered/contains\", \"\", group, elem)\n" +
-            "\n" +
-            "\t\tString multiplicities\n" +
-            "\t\tString lower_card\n" +
-            "\t\tString upper_card\n" +
-            "\t\tif (element_eq(read_attribute(model, class, \"lower_cardinality\"), read_root())):\n" +
-            "\t\t\tlower_card = \"*\"\n" +
-            "\t\telse:\n" +
-            "\t\t\tlower_card = cast_value(read_attribute(model, class, \"lower_cardinality\"))\n" +
-            "\t\tif (element_eq(read_attribute(model, class, \"upper_cardinality\"), read_root())):\n" +
-            "\t\t\tupper_card = \"*\"\n" +
-            "\t\telse:\n" +
-            "\t\t\tupper_card = cast_value(read_attribute(model, class, \"upper_cardinality\"))\n" +
-            "\t\tmultiplicities = (((\"[\" + lower_card) + \"..\") + upper_card) + \"]\"\n" +
-            "\n" +
-            "\t\telem = instantiate_node(model, \"rendered/Text\", \"\")\n" +
-            "\t\tinstantiate_attribute(model, elem, \"x\", 5)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"y\", 3)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"lineWidth\", 1)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"lineColour\", \"black\")\n" +
-            "\t\tif (element_neq(read_attribute(model, class, \"name\"), read_root())):\n" +
-            "\t\t\tinstantiate_attribute(model, elem, \"text\", string_join(read_attribute(model, class, \"name\"), \"  \" + multiplicities))\n" +
-            "\t\telse:\n" +
-            "\t\t\tinstantiate_attribute(model, elem, \"text\", \"(unnamed) \" + multiplicities)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"layer\", 2)\n" +
-            "\t\tinstantiate_link(model, \"rendered/contains\", \"\", group, elem)\n" +
-            "\n" +
-            "\t\telem = instantiate_node(model, \"rendered/Line\", \"\")\n" +
-            "\t\tinstantiate_attribute(model, elem, \"x\", 0)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"y\", 20)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"targetX\", 150)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"targetY\", 20)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"lineWidth\", 1)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"lineColour\", \"black\")\n" +
-            "\t\tinstantiate_attribute(model, elem, \"arrow\", False)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"layer\", 2)\n" +
-            "\t\tinstantiate_link(model, \"rendered/contains\", \"\", group, elem)\n" +
-            "\n" +
-            "\t\tattrs = getInstantiatableAttributes(model, class, \"abstract/AttributeLink\")\n" +
-            "\t\tattr_keys = dict_keys(attrs)\n" +
-            "\t\twhile (dict_len(attr_keys) > 0):\n" +
-            "\t\t\tattr_key = set_pop(attr_keys)\n" +
-            "\t\t\telem = instantiate_node(model, \"rendered/Text\", \"\")\n" +
-            "\t\t\tinstantiate_attribute(model, elem, \"x\", 5)\n" +
-            "\t\t\tinstantiate_attribute(model, elem, \"y\", text_loc + 20)\n" +
-            "\t\t\tinstantiate_attribute(model, elem, \"lineWidth\", 1)\n" +
-            "\t\t\tinstantiate_attribute(model, elem, \"lineColour\", \"black\")\n" +
-            "\t\t\tinstantiate_attribute(model, elem, \"text\", (attr_key + \" : \") + cast_string(list_read(string_split_nr(attrs[attr_key], \"/\", 1), 1)))\n" +
-            "\t\t\tinstantiate_attribute(model, elem, \"layer\", 2)\n" +
-            "\t\t\tinstantiate_link(model, \"rendered/contains\", \"\", group, elem)\n" +
-            "\t\t\ttext_loc = text_loc + 15\n" +
-            "\n" +
-            "\t\tinstantiate_link(model, \"TracabilityClass\", \"\", class, group)\n" +
-            "\n" +
-            "\t// Flush all associations\n" +
-            "\telements = allInstances(model, \"rendered/ConnectingLine\")\n" +
-            "\twhile (set_len(elements) > 0):\n" +
-            "\t\tclass = set_pop(elements)\n" +
-            "\t\tmodel_delete_element(model, class)\n" +
-            "\n" +
-            "\t// Rerender associations\n" +
-            "\telements = allInstances(model, \"abstract/Association\")\n" +
-            "\twhile (set_len(elements) > 0):\n" +
-            "\t\tclass = set_pop(elements)\n" +
-            "\n" +
-            "\t\tattr_keys = dict_keys(getAttributeList(model, class))\n" +
-            "\n" +
-            "\t\telem = instantiate_link(model, \"rendered/ConnectingLine\", \"\", groups[readAssociationSource(model, class)], groups[readAssociationDestination(model, class)])\n" +
-            "\t\tinstantiate_attribute(model, elem, \"offsetSourceX\", 75)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"offsetSourceY\", 30)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"offsetTargetX\", 75)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"offsetTargetY\", 30)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"lineWidth\", 1)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"lineColour\", \"black\")\n" +
-            "\t\tinstantiate_attribute(model, elem, \"arrow\", True)\n" +
-            "\t\tinstantiate_attribute(model, elem, \"__asid\", list_read(string_split_nr(class, \"/\", 1), 1))\n" +
-            "\t\tinstantiate_attribute(model, elem, \"layer\", 0)\n" +
-            "\t\tlog(\"Real ASID: \" + cast_value(class))\n" +
-            "\t\tlog(\"Found ASID \" + cast_value(list_read(string_split_nr(class, \"/\", 1), 1)))\n" +
-            "\t\tinstantiate_link(model, \"rendered/contains\", \"\", group, elem)\n" +
-            "\n" +
-            "\treturn True!";
-
-        return trans;
-    }
-
-}

+ 1 - 1
doc/conf.py

@@ -26,7 +26,7 @@ author = 'The AToMPM Team'
 # The short X.Y version
 # The short X.Y version
 version = ''
 version = ''
 # The full version, including alpha/beta/rc tags
 # The full version, including alpha/beta/rc tags
-release = '0.8.1'
+release = '0.8.2'
 
 
 
 
 # -- General configuration ---------------------------------------------------
 # -- General configuration ---------------------------------------------------

+ 0 - 15
doc/toolbars_and_plugins.rst

@@ -59,18 +59,3 @@ To export metamodels or models in AToMPM, follow these steps:
 
 
 10. If you want to use the exported file in Eclipse, you have to register the metamodel.
 10. If you want to use the exported file in Eclipse, you have to register the metamodel.
 
 
-
-ModelVerse Toolbar
-------------------
-
-.. warning:: The ModelVerse toolbar is currently in an alpha state. It is only intended as a prototype and should not be used for everyday use, as data loss is certain to occur.
-
-The ModelVerse toolbar is intended to allow for the user to load and save models to/from AToMPM to the Modelverse. 
-
-.. warning:: Currently, only metamodels in the SimpleClassDiagram formalism can be loaded and saved, along with instance models.
-
-The first button on the toolbar connects to a running ModelVerse instance running on the current machine.
-
-The second button loads a model from the ModelVerse into the current AToMPM canvas.
-
-The third button saves the current AToMPM model to the ModelVerse.

+ 23 - 5
httpwsd.js

@@ -542,9 +542,16 @@ var httpserver = _http.createServer(
 			{
 			{
 				req.setEncoding('utf8');
 				req.setEncoding('utf8');
 
 
-				var reqData = '',
+				let reqData = '',
 					 tmpzip	= 'upload'+Date.now()+'.zip',
 					 tmpzip	= 'upload'+Date.now()+'.zip',
 					 destdir	= './users/'+url.pathname.match(/(.*)\.file$/)[1]+'/';
 					 destdir	= './users/'+url.pathname.match(/(.*)\.file$/)[1]+'/';
+
+				if( url.pathname.contains("..") || url.pathname.contains(";") ) {
+					__respond(resp, 404,
+						'invalid pathname, no semicolons or .. allowed :: ' + url.pathname);
+					return;
+				}
+
 				req.addListener("data", function(chunk) {reqData += chunk;});
 				req.addListener("data", function(chunk) {reqData += chunk;});
 				req.addListener("end", 
 				req.addListener("end", 
 					function() 
 					function() 
@@ -570,7 +577,10 @@ var httpserver = _http.createServer(
 														__respond(resp,500,String(err));
 														__respond(resp,500,String(err));
 													else
 													else
 														__respond(resp,200);
 														__respond(resp,200);
-													_fs.unlink(destdir+tmpzip);
+													_fs.unlink(destdir+tmpzip, function(err){
+														console.log("Unlinked " + destdir + tmpzip);
+														}
+													);
 												});
 												});
 										});
 										});
 							});
 							});
@@ -580,12 +590,18 @@ var httpserver = _http.createServer(
 			/* serve specified file/folder within a zip file */ 
 			/* serve specified file/folder within a zip file */ 
 			else if( req.method == 'GET' && url.pathname.match(/\.file$/) )
 			else if( req.method == 'GET' && url.pathname.match(/\.file$/) )
 			{
 			{
-				var matches  = url.pathname.match(/^\/(.*?)\/(.*)\.file$/),
+				let matches  = url.pathname.match(/^\/(.*?)\/(.*)\.file$/),
 					 username = matches[1],
 					 username = matches[1],
  					 fname 	 = './'+matches[2],
  					 fname 	 = './'+matches[2],
 					 userdir	 = './users/'+username+'/',
 					 userdir	 = './users/'+username+'/',
 					 tmpzip	 = 'download'+Date.now()+'.zip';
 					 tmpzip	 = 'download'+Date.now()+'.zip';
 
 
+				if( username.contains("..") || username.contains(";") ) {
+					__respond(resp, 404,
+						'invalid username, no colons or .. allowed :: ' + username);
+					return;
+				}
+
 				_fs.exists(userdir+fname,
 				_fs.exists(userdir+fname,
 					function(exists)
 					function(exists)
 					{
 					{
@@ -599,14 +615,16 @@ var httpserver = _http.createServer(
 									if( err )
 									if( err )
 										__respond(resp,500,String(err));
 										__respond(resp,500,String(err));
 									else
 									else
-										_fs.readFile(userdir+tmpzip,'binary',
+										_fs.readFile(userdir+tmpzip,
 											function(err, data)
 											function(err, data)
 											{
 											{
 												__respond(resp,200,'',data,
 												__respond(resp,200,'',data,
 													{'Content-Type':'application/zip',
 													{'Content-Type':'application/zip',
 													 'Content-Disposition':
 													 'Content-Disposition':
 													 	'attachment; filename="'+tmpzip+'"'});
 													 	'attachment; filename="'+tmpzip+'"'});
-												_fs.unlink(userdir+tmpzip);
+												_fs.unlink(userdir+tmpzip, function(err){
+													console.log("Unlinked " + userdir+tmpzip);
+												});
 											});
 											});
 								});
 								});
 					});
 					});

+ 3 - 4
nightwatch.conf.js

@@ -3,9 +3,8 @@
 *  See COPYING, COPYING.lesser, and README.md for full details
 *  See COPYING, COPYING.lesser, and README.md for full details
 */
 */
 
 
-const seleniumServer = require("selenium-server");
 const chromedriver = require("chromedriver");
 const chromedriver = require("chromedriver");
-
+const selenium_server = require("selenium-server");
 
 
 
 
 module.exports = {
 module.exports = {
@@ -17,8 +16,8 @@ module.exports = {
   "globals_path" : "",
   "globals_path" : "",
 
 
   "selenium" : {
   "selenium" : {
-    "start_process" : true,
-    "server_path" : seleniumServer.path,
+    "start_process" : false,
+    "server_path" : selenium_server.path,
     "log_path" : "",
     "log_path" : "",
     "port" : 4444,
     "port" : 4444,
     "cli_args" : {
     "cli_args" : {

File diff suppressed because it is too large
+ 455 - 399
package-lock.json


+ 5 - 5
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "atompm",
   "name": "atompm",
-  "version": "0.8.1",
+  "version": "0.8.2",
   "description": "A Tool for Multi-Paradigm Modelling",
   "description": "A Tool for Multi-Paradigm Modelling",
   "license": "LGPL-3.0-only",
   "license": "LGPL-3.0-only",
   "homepage": "https://atompm.github.io/",
   "homepage": "https://atompm.github.io/",
@@ -16,10 +16,10 @@
     "socket.io-client": "^0.9.16"
     "socket.io-client": "^0.9.16"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "chromedriver": "^2.43.1",
-    "glob": "^7.1.2",
-    "nightwatch": "^0.9.21",
-    "selenium-server": "^3.13.0"
+    "chromedriver": "^2.46.0",
+    "glob": "^7.1.4",
+    "nightwatch": "^1.1.13",
+    "selenium-server": "3.141.59"
   },
   },
   "scripts": {
   "scripts": {
     "test": "./run_tests.sh"
     "test": "./run_tests.sh"

+ 7 - 6
packaging/package.sh

@@ -5,17 +5,18 @@
 #   i. In AToMPM - client/constants.js
 #   i. In AToMPM - client/constants.js
 #   ii. In documentation - doc/conf.py
 #   ii. In documentation - doc/conf.py
 #   iii. In Node - package.json
 #   iii. In Node - package.json
-#2. Create a new release on GitHub
-#3. The tag should be something like v0.8.0
-#4. Run this script, which will download the latest tagged version
+#2. Push these changes to GitHub
+#3. Create a new release on GitHub
+#4. The tag should be something like v0.8.0
+#5. Run this script, which will download the latest tagged version
 #   and package everything
 #   and package everything
 #   - Run it for the Python2 and the Python3 version
 #   - Run it for the Python2 and the Python3 version
 #   - Fix up the files in the package
 #   - Fix up the files in the package
 #        - Delete the unused Python directory in each zip
 #        - Delete the unused Python directory in each zip
-#5. Upload the package .zip to the release on GitHub
-#6. Publish to npm repo
+#6. Upload the package .zip to the release on GitHub
+#7. Publish to npm repo
 
 
-version="v0.8.1-rc4"
+version="v0.8.2"
 
 
 package_python3=true
 package_python3=true
 
 

+ 14 - 3
run_tests.sh

@@ -29,15 +29,26 @@ if ! kill -0 "$mtpid"; then
     exit $mt_status
     exit $mt_status
 fi
 fi
 
 
-echo "Starting tests..."
+echo "Starting Selenium server."
+java -jar "./node_modules/selenium-server/lib/runner/selenium-server-standalone-3.141.59.jar" &
+seleniumpid=$!
+sleep 3
+
+#check if model transformer is dead
+if ! kill -0 "$seleniumpid"; then
+    wait seleniumpid
+    se_status=$?
+    exit $se_status
+fi
 
 
-#start nightwatch tests
-nightwatch
 
 
+echo "Starting tests..."
+nightwatch
 
 
 echo "Stopping server and mt script..."
 echo "Stopping server and mt script..."
 kill "$serverpid"
 kill "$serverpid"
 kill "$mtpid"
 kill "$mtpid"
+kill "$seleniumpid"
 
 
 
 
 
 

+ 0 - 610
users/(default)/Toolbars/ModelVerse/ModelVerse.buttons.model

@@ -1,610 +0,0 @@
-{
-	"csm": {
-		"nodes": {
-			"0": {
-				"typename": {
-					"type": "string",
-					"value": "ButtonIcon"
-				},
-				"position": {
-					"type": "list<double>",
-					"value": [
-						499,
-						271
-					]
-				},
-				"orientation": {
-					"type": "double",
-					"value": 0
-				},
-				"scale": {
-					"type": "list<double>",
-					"value": [
-						1,
-						1
-					]
-				},
-				"mapper": {
-					"type": "code",
-					"value": ""
-				},
-				"parser": {
-					"type": "code",
-					"value": ""
-				},
-				"$contents": {
-					"type": "map<string,*>",
-					"value": {
-						"nodes": {
-							"1": {
-								"width": {
-									"type": "double",
-									"value": "120"
-								},
-								"height": {
-									"type": "double",
-									"value": "50"
-								},
-								"cornerRadius": {
-									"type": "double",
-									"value": "25"
-								},
-								"style": {
-									"type": "map<string,string>",
-									"value": {
-										"stroke": "#af0000",
-										"stroke-dasharray": "",
-										"fill": "#000000",
-										"fill-opacity": 0.05,
-										"stroke-width": 2
-									}
-								},
-								"mapper": {
-									"type": "code",
-									"value": ""
-								},
-								"parser": {
-									"type": "code",
-									"value": ""
-								},
-								"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Rectangle",
-								"position": {
-									"type": "list<double>",
-									"value": [
-										0,
-										0
-									]
-								},
-								"orientation": {
-									"type": "double",
-									"value": 0
-								},
-								"scale": {
-									"type": "list<double>",
-									"value": [
-										1,
-										1
-									]
-								}
-							},
-							"2": {
-								"textContent": {
-									"type": "string",
-									"value": "connectMV"
-								},
-								"style": {
-									"type": "map<string,string>",
-									"value": {
-										"stroke": "#000000",
-										"stroke-dasharray": "",
-										"fill": "#ffffff",
-										"fill-opacity": 0.75,
-										"font-size": "13px",
-										"stroke-width": 1
-									}
-								},
-								"mapper": {
-									"type": "code",
-									"value": "({\"textContent\":getAttr(\"name\")})"
-								},
-								"parser": {
-									"type": "code",
-									"value": "({\"name\":getAttr(\"textContent\")})"
-								},
-								"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Text",
-								"position": {
-									"type": "list<double>",
-									"value": [
-										10,
-										13
-									]
-								},
-								"orientation": {
-									"type": "double",
-									"value": 0
-								},
-								"scale": {
-									"type": "list<double>",
-									"value": [
-										1,
-										1
-									]
-								}
-							},
-							"3": {
-								"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Contain",
-								"position": {
-									"type": "list<double>",
-									"value": [
-										17.74899850809561,
-										12.998998508095553
-									]
-								},
-								"orientation": {
-									"type": "double",
-									"value": 0
-								},
-								"scale": {
-									"type": "list<double>",
-									"value": [
-										1,
-										1
-									]
-								},
-								"link-style": {
-									"type": "map<string,string>",
-									"value": {
-										"stroke": "#00ffff",
-										"stroke-dasharray": "",
-										"stroke-opacity": 0.1,
-										"arrow-start": "none",
-										"arrow-end": "classic-wide-long"
-									}
-								}
-							}
-						},
-						"edges": [
-							{
-								"src": "1",
-								"dest": 3
-							},
-							{
-								"src": 3,
-								"dest": "2"
-							}
-						]
-					}
-				},
-				"$asuri": {
-					"type": "string",
-					"value": "/Formalisms/__Utilities__/Buttons/Buttons/Button/0.instance"
-				},
-				"$type": "/Formalisms/__Utilities__/Buttons/Buttons.defaultIcons/ButtonIcon"
-			},
-			"1": {
-				"typename": {
-					"type": "string",
-					"value": "ButtonIcon"
-				},
-				"position": {
-					"type": "list<double>",
-					"value": [
-						708,
-						315
-					]
-				},
-				"orientation": {
-					"type": "double",
-					"value": 0
-				},
-				"scale": {
-					"type": "list<double>",
-					"value": [
-						1,
-						1
-					]
-				},
-				"mapper": {
-					"type": "code",
-					"value": ""
-				},
-				"parser": {
-					"type": "code",
-					"value": ""
-				},
-				"$contents": {
-					"type": "map<string,*>",
-					"value": {
-						"nodes": {
-							"1": {
-								"width": {
-									"type": "double",
-									"value": "120"
-								},
-								"height": {
-									"type": "double",
-									"value": "50"
-								},
-								"cornerRadius": {
-									"type": "double",
-									"value": "25"
-								},
-								"style": {
-									"type": "map<string,string>",
-									"value": {
-										"stroke": "#af0000",
-										"stroke-dasharray": "",
-										"fill": "#000000",
-										"fill-opacity": 0.05,
-										"stroke-width": 2
-									}
-								},
-								"mapper": {
-									"type": "code",
-									"value": ""
-								},
-								"parser": {
-									"type": "code",
-									"value": ""
-								},
-								"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Rectangle",
-								"position": {
-									"type": "list<double>",
-									"value": [
-										0,
-										0
-									]
-								},
-								"orientation": {
-									"type": "double",
-									"value": 0
-								},
-								"scale": {
-									"type": "list<double>",
-									"value": [
-										1,
-										1
-									]
-								}
-							},
-							"2": {
-								"textContent": {
-									"type": "string",
-									"value": "loadModel"
-								},
-								"style": {
-									"type": "map<string,string>",
-									"value": {
-										"stroke": "#000000",
-										"stroke-dasharray": "",
-										"fill": "#ffffff",
-										"fill-opacity": 0.75,
-										"font-size": "13px",
-										"stroke-width": 1
-									}
-								},
-								"mapper": {
-									"type": "code",
-									"value": "({\"textContent\":getAttr(\"name\")})"
-								},
-								"parser": {
-									"type": "code",
-									"value": "({\"name\":getAttr(\"textContent\")})"
-								},
-								"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Text",
-								"position": {
-									"type": "list<double>",
-									"value": [
-										10,
-										13
-									]
-								},
-								"orientation": {
-									"type": "double",
-									"value": 0
-								},
-								"scale": {
-									"type": "list<double>",
-									"value": [
-										1,
-										1
-									]
-								}
-							},
-							"3": {
-								"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Contain",
-								"position": {
-									"type": "list<double>",
-									"value": [
-										17.74899850809561,
-										12.998998508095553
-									]
-								},
-								"orientation": {
-									"type": "double",
-									"value": 0
-								},
-								"scale": {
-									"type": "list<double>",
-									"value": [
-										1,
-										1
-									]
-								},
-								"link-style": {
-									"type": "map<string,string>",
-									"value": {
-										"stroke": "#00ffff",
-										"stroke-dasharray": "",
-										"stroke-opacity": 0.1,
-										"arrow-start": "none",
-										"arrow-end": "classic-wide-long"
-									}
-								}
-							}
-						},
-						"edges": [
-							{
-								"src": "1",
-								"dest": 3
-							},
-							{
-								"src": 3,
-								"dest": "2"
-							}
-						]
-					}
-				},
-				"$asuri": {
-					"type": "string",
-					"value": "/Formalisms/__Utilities__/Buttons/Buttons/Button/1.instance"
-				},
-				"$type": "/Formalisms/__Utilities__/Buttons/Buttons.defaultIcons/ButtonIcon"
-			},
-			"21": {
-				"typename": {
-					"type": "string",
-					"value": "ButtonIcon"
-				},
-				"position": {
-					"type": "list<double>",
-					"value": [
-						866,
-						384
-					]
-				},
-				"orientation": {
-					"type": "double",
-					"value": 0
-				},
-				"scale": {
-					"type": "list<double>",
-					"value": [
-						1,
-						1
-					]
-				},
-				"mapper": {
-					"type": "code",
-					"value": ""
-				},
-				"parser": {
-					"type": "code",
-					"value": ""
-				},
-				"$contents": {
-					"type": "map<string,*>",
-					"value": {
-						"nodes": {
-							"1": {
-								"width": {
-									"type": "double",
-									"value": "120"
-								},
-								"height": {
-									"type": "double",
-									"value": "50"
-								},
-								"cornerRadius": {
-									"type": "double",
-									"value": "25"
-								},
-								"style": {
-									"type": "map<string,string>",
-									"value": {
-										"stroke": "#af0000",
-										"stroke-dasharray": "",
-										"fill": "#000000",
-										"fill-opacity": 0.05,
-										"stroke-width": 2
-									}
-								},
-								"mapper": {
-									"type": "code",
-									"value": ""
-								},
-								"parser": {
-									"type": "code",
-									"value": ""
-								},
-								"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Rectangle",
-								"position": {
-									"type": "list<double>",
-									"value": [
-										0,
-										0
-									]
-								},
-								"orientation": {
-									"type": "double",
-									"value": 0
-								},
-								"scale": {
-									"type": "list<double>",
-									"value": [
-										1,
-										1
-									]
-								}
-							},
-							"2": {
-								"textContent": {
-									"type": "string",
-									"value": "saveModel"
-								},
-								"style": {
-									"type": "map<string,string>",
-									"value": {
-										"stroke": "#000000",
-										"stroke-dasharray": "",
-										"fill": "#ffffff",
-										"fill-opacity": 0.75,
-										"font-size": "13px",
-										"stroke-width": 1
-									}
-								},
-								"mapper": {
-									"type": "code",
-									"value": "({\"textContent\":getAttr(\"name\")})"
-								},
-								"parser": {
-									"type": "code",
-									"value": "({\"name\":getAttr(\"textContent\")})"
-								},
-								"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Text",
-								"position": {
-									"type": "list<double>",
-									"value": [
-										10,
-										13
-									]
-								},
-								"orientation": {
-									"type": "double",
-									"value": 0
-								},
-								"scale": {
-									"type": "list<double>",
-									"value": [
-										1,
-										1
-									]
-								}
-							},
-							"3": {
-								"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Contain",
-								"position": {
-									"type": "list<double>",
-									"value": [
-										17.74899850809561,
-										12.998998508095553
-									]
-								},
-								"orientation": {
-									"type": "double",
-									"value": 0
-								},
-								"scale": {
-									"type": "list<double>",
-									"value": [
-										1,
-										1
-									]
-								},
-								"link-style": {
-									"type": "map<string,string>",
-									"value": {
-										"stroke": "#00ffff",
-										"stroke-dasharray": "",
-										"stroke-opacity": 0.1,
-										"arrow-start": "none",
-										"arrow-end": "classic-wide-long"
-									}
-								}
-							}
-						},
-						"edges": [
-							{
-								"src": "1",
-								"dest": 3
-							},
-							{
-								"src": 3,
-								"dest": "2"
-							}
-						]
-					}
-				},
-				"$asuri": {
-					"type": "string",
-					"value": "/Formalisms/__Utilities__/Buttons/Buttons/Button/21.instance"
-				},
-				"$type": "/Formalisms/__Utilities__/Buttons/Buttons.defaultIcons/ButtonIcon"
-			}
-		},
-		"edges": [],
-		"metamodels": [
-			"/Formalisms/__Utilities__/Buttons/Buttons.defaultIcons",
-			"/Formalisms/__LanguageSyntax__/SimpleClassDiagram/SimpleClassDiagram.defaultIcons",
-			"/Formalisms/__LanguageSyntax__/SimpleClassDiagram/SimpleClassDiagram.umlIcons",
-			"/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax.defaultIcons",
-			"/Formalisms/SCCD/SCCD.defaultIcons"
-		]
-	},
-	"asm": {
-		"nodes": {
-			"0": {
-				"name": {
-					"type": "string",
-					"value": "connectMV"
-				},
-				"tooltip": {
-					"type": "string",
-					"value": "(ALPHA) Connect to the ModelVerse"
-				},
-				"code": {
-					"type": "code",
-					"value": "new ModelVerseConnector();\nModelVerseConnector.connect();"
-				},
-				"$type": "/Formalisms/__Utilities__/Buttons/Buttons/Button"
-			},
-			"1": {
-				"name": {
-					"type": "string",
-					"value": "loadModel"
-				},
-				"tooltip": {
-					"type": "string",
-					"value": "(ALPHA) Load a model from the ModelVerse"
-				},
-				"code": {
-					"type": "code",
-					"value": "if (ModelVerseConnector.connected == undefined){\n    WindowManagement.openDialog(_ERROR,'Connect to the ModelVerse first');\n}else{\n    ModelVerseConnector.choose_model();\n}"
-				},
-				"$type": "/Formalisms/__Utilities__/Buttons/Buttons/Button"
-			},
-			"21": {
-				"name": {
-					"type": "string",
-					"value": "saveModel"
-				},
-				"tooltip": {
-					"type": "string",
-					"value": "(ALPHA) Save a model to the ModelVerse"
-				},
-				"code": {
-					"type": "code",
-					"value": "if (ModelVerseConnector.connected == undefined){\n    WindowManagement.openDialog(_ERROR,'Connect to the ModelVerse first');\n}else{\n    _httpReq('GET', '/current.state?wid='+_context.aswid, undefined,                \n    ModelVerseConnector.choose_model);\n}"
-				},
-				"$type": "/Formalisms/__Utilities__/Buttons/Buttons/Button"
-			}
-		},
-		"edges": [],
-		"metamodels": [
-			"/Formalisms/__Utilities__/Buttons/Buttons",
-			"/Formalisms/__LanguageSyntax__/SimpleClassDiagram/SimpleClassDiagram",
-			"/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax",
-			"/Formalisms/SCCD/SCCD"
-		]
-	}
-}

BIN
users/(default)/Toolbars/ModelVerse/connectMV.icon.png


BIN
users/(default)/Toolbars/ModelVerse/loadModel.icon.png


BIN
users/(default)/Toolbars/ModelVerse/saveModel.icon.png