Преглед изворни кода

Merge pull request #71 from AToMPM/MV-save

Improve loading and saving of ModelVerse models.
BentleyJOakes пре 6 година
родитељ
комит
5d19815a8d

+ 1 - 1
client/atompm.html

@@ -42,10 +42,10 @@
 		<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/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/collaboration.js"></script>
 		<script text="text/javascript" src="client/layout.js"></script>
-		<script text="text/javascript" src="client/modelverse_connector.js"></script>
 		<script text="text/javascript" src="client/client.js"></script>
 		<script text="text/javascript" src="styleinfo.js"></script>
         <link rel="icon" href="favicon.png">

+ 6 - 3
client/http_utils.js

@@ -64,9 +64,11 @@ HttpUtils = function(){
 			req.open(method, url, !sync); 
 			req.onreadystatechange = onreadystatechange;
 
-			let paramValue = (typeof params == "string")?
-				params : utils.jsons(params);
-			req.send(paramValue);
+			if (typeof params != 'string'){
+				params = JSON.stringify(params);
+			}
+			req.send(params);
+
 		}
 	};
 	
@@ -221,6 +223,7 @@ HttpUtils = function(){
 		var _context = {
 				'username':__user,
 				'wid':__wid,
+				'aswid' :__aswid,
 				'mms':utils.keys(__loadedToolbars).filter(__isIconMetamodel)};
 		try			{eval(code); return {};}
 		catch(err)	

Разлика између датотеке није приказан због своје велике величине
+ 732 - 466
client/modelverse_connector.js


+ 333 - 0
client/modelverse_connector_rendering.js

@@ -0,0 +1,333 @@
+/* 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 - 348
tests/05_creating_dsl.js

@@ -728,354 +728,7 @@ module.exports = {
 
 
     },
-
-
-    'Create CS model': function (client) {
-
-        let filename = '/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax.defaultIcons.metamodel';
-        test_utils.load_toolbar(client, [filename]);
-
-        let classIcon = "#\\/Formalisms\\/__LanguageSyntax__\\/ConcreteSyntax\\/ConcreteSyntax\\.defaultIcons\\.metamodel\\/IconIcon";
-        client.waitForElementPresent(classIcon, 2000, "Check for class icon...");
-        client.click(classIcon);
-
-        let canvas = "#div_canvas";
-        client.waitForElementPresent(canvas, 1000, "Checking for canvas...");
-
-        let test_folder = "autotest";
-        let name_field = "#tr_typename > td:nth-child(2) > textarea";
-        let num_elements = 0;
-
-        //BUILD CLASSES
-        let icon_type = "#\\/Formalisms\\/__LanguageSyntax__\\/ConcreteSyntax\\/ConcreteSyntax\\.defaultIcons\\/IconIcon\\/";
-
-        let start_x = 200;
-        let x_diff = 250;
-        let x_coords = [start_x, start_x + x_diff, start_x + 2 * x_diff];
-
-        let start_y = 150;
-        let y_diff = 180;
-        let y_coords = [start_y, start_y + y_diff, start_y + 2 * y_diff];
-
-        let num_classes = x_coords.length * y_coords.length;
-
-        num_elements = model_building_utils.create_classes(client, x_coords, y_coords, num_elements, icon_type);
-
-        //SET NAMES FOR CLASSES
-        for (let i = 0; i < num_classes; i++) {
-            let class_name = "Class" + String.fromCharCode(65 + i) + "Icon";
-            let attrs = {};
-            attrs[name_field] = class_name;
-            model_building_utils.set_attribs(client, i, attrs, icon_type);
-        }
-
-        // BUILD TEXT FOR ICONS
-        let textIcon = "#\\/Formalisms\\/__LanguageSyntax__\\/ConcreteSyntax\\/ConcreteSyntax\\.defaultIcons\\.metamodel\\/TextIcon";
-        let textType = "#\\/Formalisms\\/__LanguageSyntax__\\/ConcreteSyntax\\/ConcreteSyntax\\.defaultIcons\\/TextIcon\\/";
-        let textContent_field = "#tr_textContent > td:nth-child(2) > textarea";
-
-        client.waitForElementPresent(textIcon, 2000, "Check for text icon...");
-        client.click(textIcon);
-
-        for (let i = 0; i < num_classes; i++) {
-
-            let text = "Class" + String.fromCharCode(65 + i);
-
-            let textDiv = model_building_utils.build_div(textType, num_elements);
-            let iconDiv = model_building_utils.build_div(icon_type, i);
-
-            let attrs = {};
-            attrs[textContent_field] = text;
-
-            client
-                .pause(300)
-                .moveToElement(canvas, 20, 200)
-                .mouseButtonClick('right')
-                .pause(500)
-                .waitForElementPresent(textDiv, 500, "Created text: " + textDiv);
-
-            model_building_utils.set_attribs(client, num_elements, attrs, textType);
-
-            num_elements++;
-
-            client.moveToElement(textDiv, 10, 10)
-                .mouseButtonClick('left')
-                .pause(300)
-                .mouseButtonDown('left')
-                .pause(300);
-
-            model_building_utils.move_to_element_ratio(client, iconDiv, 35, 15);
-            client.mouseButtonUp('left');
-
-            model_building_utils.click_off(client);
-
-            //inner link counts as an element
-            num_elements++;
-        }
-
-
-        // BUILD SYMBOLS FOR ICONS
-        let symbols = ["PathIcon", "CircleIcon", "StarIcon", "PolygonIcon", "EllipseIcon", "EllipseIcon", "RectangleIcon", "ImageIcon"];
-        let getIcon = function (type) {
-            return "#\\/Formalisms\\/__LanguageSyntax__\\/ConcreteSyntax\\/ConcreteSyntax\\.defaultIcons\\.metamodel\\/" + type;
-        };
-        let getType = function (type) {
-            return "#\\/Formalisms\\/__LanguageSyntax__\\/ConcreteSyntax\\/ConcreteSyntax\\.defaultIcons\\/" + type + "\\/";
-        };
-
-        for (let i = 0; i < num_classes; i++) {
-
-            let currSymbol = symbols[i % symbols.length];
-            client.waitForElementPresent(getIcon(currSymbol), 2000, "Check for symbol icon...");
-            client.click(getIcon(currSymbol));
-
-
-            let symbolDiv = model_building_utils.build_div(getType(currSymbol), num_elements);
-            let iconDiv = model_building_utils.build_div(icon_type, i);
-
-
-            client
-                .pause(300)
-                .moveToElement(canvas, 50, 200)
-                .mouseButtonClick('right')
-                .pause(1000)
-                .waitForElementPresent(symbolDiv, 500, "Created symbol: " + symbolDiv);
-
-            model_building_utils.click_off(client);
-
-            num_elements++;
-
-            model_building_utils.move_to_element_ratio(client, symbolDiv, 50, 50);
-            client
-                .mouseButtonClick('left')
-                .pause(300)
-                .mouseButtonDown('left')
-                .pause(300);
-
-            model_building_utils.move_to_element_ratio(client, iconDiv, 50, 55);
-            client.pause(300).mouseButtonUp('left');
-
-            model_building_utils.click_off(client);
-
-            //inner link counts as an element
-            num_elements++;
-        }
-
-        // BUILD LINKS
-        let linkIcon = "#\\/Formalisms\\/__LanguageSyntax__\\/ConcreteSyntax\\/ConcreteSyntax\\.defaultIcons\\.metamodel\\/LinkIcon";
-        let linkType = "#\\/Formalisms\\/__LanguageSyntax__\\/ConcreteSyntax\\/ConcreteSyntax\\.defaultIcons\\/LinkIcon\\/";
-        let link_typename_field = "#tr_typename > td:nth-child(2) > textarea";
-
-        let link_y_coords = [];
-        let link_x_coords = [start_x + 3 * x_diff, start_x + 4 * x_diff];
-
-        for (let i = 0; i < assocs.length / 2; i++) {
-            link_y_coords.push(start_y + i * y_diff);
-        }
-
-        client.waitForElementPresent(linkIcon, 2000, "Check for link icon...");
-        client.click(linkIcon);
-
-        let num_elements_before = num_elements;
-        model_building_utils.create_classes(client, link_x_coords, link_y_coords, num_elements, linkType);
-
-        //SET NAMES FOR LINKS
-        for (let i = 0; i < assocs.length; i++) {
-            let link_name = assocs[i][2] + "Link";
-            let attrs = {};
-            attrs[link_typename_field] = link_name;
-            model_building_utils.set_attribs(client, num_elements_before + i, attrs, linkType);
-        }
-
-        //remove unneeded elements
-        model_building_utils.delete_element(client, model_building_utils.build_div(icon_type, 4));
-        model_building_utils.delete_element(client, model_building_utils.build_div(linkType, 50));
-
-
-        let folder_name = "autotest";
-        model_building_utils.save_model(client, folder_name, "autotestCS.model");
-
-        model_building_utils.compile_model(client, "CS", folder_name, "autotest.defaultIcons.metamodel");
-
-        client.pause(1000);
-
-    },
-
-    'Create model': function (client) {
-
-        let test_toolbar = '/autotest/autotest.defaultIcons.metamodel';
-        test_utils.load_toolbar(client, [test_toolbar]);
-
-        let class_names = [];
-        for (let i = 0; i < 9; i++) {
-            let class_name = "Class" + String.fromCharCode(65 + i) + "Icon";
-
-            if (class_name == "ClassEIcon") {
-                continue; //skip ClassEIcon
-            }
-            class_names.push(class_name);
-        }
-
-        //BUILD CLASSES
-        let class_icon = "#\\2f autotest\\2f autotest\\2e defaultIcons\\2e metamodel\\2f ";
-        let class_type = "#\\2f autotest\\2f autotest\\2e defaultIcons\\2f ";
-
-        let start_x = 200;
-        let x_diff = 300;
-        let x_coords = [start_x, start_x + x_diff, start_x + 2 * x_diff];
-
-        let start_y = 150;
-        let y_diff = 180;
-        let y_coords = [start_y, start_y + y_diff, start_y + 2 * y_diff];
-
-        let coords = [];
-        for (let x of x_coords) {
-            for (let y of y_coords) {
-                coords.push([x, y]);
-            }
-        }
-
-        let num_elements = 0;
-        let element_map = {};
-
-        for (let i = 0; i < class_names.length; i++) {
-            let class_name = class_names[i];
-            let class_btn = class_icon + class_name;
-
-            client.waitForElementPresent(class_btn, 2000, "Check for class icon: " + class_btn);
-            client.click(class_btn);
-
-            let class_div = class_type + class_name + "\\2f ";
-
-            let built_class_div = model_building_utils.create_class(client, coords[i][0], coords[i][1], num_elements, class_div);
-
-            element_map[class_name] = built_class_div;
-
-            num_elements++;
-
-        }
-
-        model_building_utils.click_off(client);
-
-        // BUILD ASSOCIATIONS
-        for (let assoc of assocs) {
-            let from_class_name = "Class" + String.fromCharCode(65 + assoc[0]) + "Icon";
-            let to_class_name = "Class" + String.fromCharCode(65 + assoc[1]) + "Icon";
-
-            if (from_class_name == "ClassEIcon") {
-                from_class_name = "ClassHIcon";
-            }
-
-            if (to_class_name == "ClassEIcon") {
-                from_class_name = "ClassFIcon";
-            }
-
-            //select the text of the class
-            let text_div = " > text:nth-child(1)";
-            let from_class_div = element_map[from_class_name] + text_div;
-            let to_class_div = element_map[to_class_name] + text_div;
-
-            // console.log(from_class_div);
-            // console.log(to_class_div);
-
-
-            let isContainAssoc = assoc[3];
-            if (!isContainAssoc) {
-                model_building_utils.move_to_element_ratio(client, from_class_div, 20, 50);
-                client.mouseButtonDown('right');
-                model_building_utils.move_to_element_ratio(client, to_class_div, 80, 50);
-                client.mouseButtonUp('right').pause(2000);
-            } else {
-                model_building_utils.move_to_element_ratio(client, to_class_div, 30, 50);
-                client.mouseButtonClick('left').pause(300);
-                client.mouseButtonDown('left');
-                model_building_utils.move_to_element_ratio(client, from_class_div, 50, 120);
-                client.mouseButtonUp('left').pause(300);
-            }
-
-            num_elements++;
-
-            model_building_utils.click_off(client);
-
-        }
-
-        //SCALE AND ROTATE TESTS
-        let scale_element_div = "#\\/autotest\\/autotest\\.defaultIcons\\/ClassDIcon\\/3\\.instance";
-        model_building_utils.move_to_element_ratio(client, scale_element_div, 50, 50);
-        client.mouseButtonClick('left').pause(300);
-        //client.setValue(scale_element_div, client.Keys.CONTROL);
-
-        //TODO: Can't send CONTROL key
-        client.execute(function () {
-            GeometryUtils.showGeometryControlsOverlay();
-        }, [], null);
-
-
-        let resize_btn_div = "#resize_btn";
-        let resizeH_btn_div = "#resizeH_btn";
-        let resizeW_btn_div = "#resizeW_btn";
-        let rotate_btn_div = "#rotate_btn";
-        let ok_btn_div = "#ok_btn";
-
-        model_building_utils.scroll_geometry_element(client, resize_btn_div, 120, 8);
-        model_building_utils.scroll_geometry_element(client, resizeH_btn_div, -120, 4);
-        model_building_utils.scroll_geometry_element(client, resizeW_btn_div, -120, 4);
-        model_building_utils.scroll_geometry_element(client, rotate_btn_div, 120, 8);
-        client.click(ok_btn_div).pause(500);
-
-        model_building_utils.click_off(client);
-
-        //SET ATTRIBUTES
-
-        let IClass = "#\\/autotest\\/autotest\\.defaultIcons\\/ClassIIcon\\/";
-
-        let AAttribs = {};
-        AAttribs['int'] = 123;
-        AAttribs['string'] = "bonjour";
-        AAttribs['float'] = "123.456";
-        AAttribs['boolean'] = false;
-
-        let attribs = {};
-        for (let [key, value] of Object.entries(AAttribs)) {
-            let new_key = "#tr_" + key + " > td:nth-child(2) > textarea:nth-child(1)";
-            attribs[new_key] = value;
-        }
-        //TODO: Set other attribs
-        let div_suffix = " > text";
-        model_building_utils.set_attribs(client, 7, attribs, IClass, div_suffix, [1, 1]);
-
-
-        // VERIFY MODEL
-        let verify_btn = "#\\/Toolbars\\/MainMenu\\/MainMenu\\.buttons\\.model\\/validateM";
-        let dialog_btn = "#dialog_btn";
-
-        client.waitForElementPresent(verify_btn, 2000, "Find verify button")
-            .click(verify_btn)
-            .waitForElementNotPresent(dialog_btn, 2000, "No constraint violation");
-
-        let new_x = start_x + 3 * x_diff;
-        let class_btn = class_icon + "ClassCIcon";
-        let CClass_type = "#\\/autotest\\/autotest\\.defaultIcons\\/ClassCIcon\\/";
-        client.click(class_btn);
-
-        model_building_utils.create_class(client, new_x, start_y, num_elements, CClass_type);
-        model_building_utils.create_class(client, new_x, start_y + y_diff, num_elements, CClass_type);
-
-        client.click(verify_btn)
-            .waitForElementPresent(dialog_btn, 2000, "Constraint violation")
-            .click(dialog_btn).pause(1000);
-
-        model_building_utils.click_off(client);
-
-
-        // SAVE INSTANCE MODEL
-        let folder_name = "autotest";
-        model_building_utils.save_model(client, folder_name, "autotest_instance.model");
-
-        client.pause(1000);
-
-
-    },
+    
 
     after: function (client) {
         client.end();

+ 4 - 0
tests/99_ecore_toolbar_test.js

@@ -31,12 +31,14 @@ module.exports = {
         client.waitForElementPresent(dialog_btn, 2000, "Load MM Menu");
         client.click(dialog_btn);
 
+
         // client.pause(3000);
 
         // let ecore_path = ecore_dir + "autotestMetamodel.ecore";
         // client.verify.ok(fs.existsSync(ecore_dir), "Check folder existance: '" + ecore_dir + "'");
         // client.verify.ok(fs.existsSync(ecore_path), "Check file existance: '" + ecore_path + "'");
 
+
     },
 
     'Export M test': function (client) {
@@ -52,12 +54,14 @@ module.exports = {
         client.waitForElementPresent(dialog_btn, 2000, "Load M Menu");
         client.click(dialog_btn);
 
+
         // client.pause(3000);
         //
         // let ecore_path = ecore_dir + "autotest_instanceModel.xmi";
         // client.verify.ok(fs.existsSync(ecore_dir), "Check folder existance: '" + ecore_dir + "'");
         // client.verify.ok(fs.existsSync(ecore_path), "Check file existance: '" + ecore_path + "'");
 
+
     },
 
     after : function (client) {

+ 207 - 5
users/(default)/Toolbars/ModelVerse/ModelVerse.buttons.model

@@ -270,7 +270,7 @@
 							"2": {
 								"textContent": {
 									"type": "string",
-									"value": "dumpModel"
+									"value": "loadModel"
 								},
 								"style": {
 									"type": "map<string,string>",
@@ -360,11 +360,195 @@
 					"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/__Utilities__/Buttons/Buttons.defaultIcons",
+			"/Formalisms/__LanguageSyntax__/SimpleClassDiagram/SimpleClassDiagram.defaultIcons",
+			"/Formalisms/__LanguageSyntax__/SimpleClassDiagram/SimpleClassDiagram.umlIcons",
+			"/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax.defaultIcons",
+			"/Formalisms/SCCD/SCCD.defaultIcons"
 		]
 	},
 	"asm": {
@@ -387,7 +571,22 @@
 			"1": {
 				"name": {
 					"type": "string",
-					"value": "dumpModel"
+					"value": "loadModel"
+				},
+				"tooltip": {
+					"type": "string",
+					"value": ""
+				},
+				"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",
@@ -395,14 +594,17 @@
 				},
 				"code": {
 					"type": "code",
-					"value": "ModelVerseConnector.dump_model()"
+					"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/__Utilities__/Buttons/Buttons",
+			"/Formalisms/__LanguageSyntax__/SimpleClassDiagram/SimpleClassDiagram",
+			"/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax",
+			"/Formalisms/SCCD/SCCD"
 		]
 	}
 }