Jelajahi Sumber

Implement and test conformance_remove

Yentl Van Tendeloo 7 tahun lalu
induk
melakukan
62a16a9870

+ 30 - 0
bootstrap/core_algorithm.alc

@@ -2359,6 +2359,34 @@ String function cmd_folder_create(folder_name : String):
 	else:
 		return "Folder exists: " + folder_name!
 
+String function cmd_conformance_delete(model_name : String, metamodel_name : String, typemapping_name : String):
+	// Remove an existing instanceOf relation
+	if (get_entry_id(model_name) != ""):
+		if (get_entry_id(metamodel_name) != ""):
+			Element links
+			String link
+			String found_typing_name
+
+			links = get_instanceOf_links(get_entry_id(model_name), get_entry_id(metamodel_name))
+			while (set_len(links) > 0):
+				// Iterate over each link and remove if type mapping matches
+				link = set_pop(links)
+				found_typing_name = anAssociationDestination(core, link, "typing")
+				if (bool_and(typemapping_name == "", found_typing_name == "")):
+					// Remove only the link
+					model_delete_element(core, link)
+				else:
+					found_typing_name = read_attribute(core, anAssociationDestination(core, link, "typing"), "name")
+					if (found_typing_name == typemapping_name):
+						// Type mappings match, so remove link
+						// Optional: type mapping model can also be removed, but is potentially in use as it is itself a model!
+						model_delete_element(core, link)
+			return "Success"!
+		else:
+			return "Model not found: " + metamodel_name!
+	else:
+		return "Model not found: " + model_name!
+
 String function cmd_conformance_add(model_name : String, metamodel_name : String):
 	// Create a new instanceOf relation now
 	if (get_entry_id(model_name) != ""):
@@ -2522,6 +2550,8 @@ Void function new_task():
 				output(cmd_folder_create(single_input("Folder name?")))
 			elif (cmd == "add_conformance"):
 				output(cmd_conformance_add(single_input("Model name?"), single_input("Metamodel name?")))
+			elif (cmd == "remove_conformance"):
+				output(cmd_conformance_delete(single_input("Model name?"), single_input("Metamodel name?"), single_input("Type mapping name?")))
 			elif (cmd == "service_poll"):
 				// TODO
 				cmd = "FAIL"

+ 138 - 1
unit/test_all.py

@@ -3081,6 +3081,144 @@ class TestModelverse(unittest.TestCase):
         except UnknownModel:
             assert model_types("users/user/test/b") == before
 
+    def test_op_conformance_delete(self):
+        model_add("users/user/test/a", "formalisms/SimpleClassDiagrams", """
+            Class A {}
+            Class B {}
+            Association C (A, B) {}
+            """)
+
+        # Add conformance bottom relation
+        conformance_add("users/user/test/a", "formalisms/Bottom")
+
+        # Verify initial state
+        ts = model_types("users/user/test/a")
+        assert len(ts) == 2
+        while ts:
+            t = ts.pop()
+            assert t[0] in ["formalisms/SimpleClassDiagrams", "formalisms/Bottom"]
+            if t[0] == "formalisms/SimpleClassDiagrams":
+                assert t[1] != None
+            elif t[1] == "formalisms/Bottom":
+                # Type mapping is empty
+                assert t[1] == None
+            assert t[2] == None
+
+        # Now remove it again
+        conformance_delete("users/user/test/a", "formalisms/Bottom", "")
+        ts = model_types("users/user/test/a")
+        assert len(ts) == 1
+        t = ts.pop()
+        assert t[0] == "formalisms/SimpleClassDiagrams"
+        assert t[1] != None
+        assert t[2] == None
+
+        # Add conformance bottom relation twice
+        conformance_add("users/user/test/a", "formalisms/Bottom")
+        conformance_add("users/user/test/a", "formalisms/Bottom")
+
+        # Should be there twice, but set flattens it to once
+        ts = model_types("users/user/test/a")
+        assert len(ts) == 2
+        while ts:
+            t = ts.pop()
+            assert t[0] in ["formalisms/SimpleClassDiagrams", "formalisms/Bottom"]
+            if t[0] == "formalisms/SimpleClassDiagrams":
+                assert t[1] != None
+            elif t[1] == "formalisms/Bottom":
+                # Type mapping is empty
+                assert t[1] == None
+            assert t[2] == None
+
+        # Now remove it (once called, but invoked for all occurences!)
+        conformance_delete("users/user/test/a", "formalisms/Bottom", "")
+
+        ts = model_types("users/user/test/a")
+        assert len(ts) == 1
+        t = ts.pop()
+        assert t[0] == "formalisms/SimpleClassDiagrams"
+        assert t[1] != None
+        assert t[2] == None
+
+        # Now actually test filtering capabilities
+        alter_context("users/user/test/a", "formalisms/Bottom")
+        element_list("users/user/test/a")
+        alter_context("users/user/test/a", "formalisms/SimpleClassDiagrams")
+
+        # Model should be there with a type mapping model
+        ts = model_types("users/user/test/a")
+        assert len(ts) == 2
+        while ts:
+            t = ts.pop()
+            assert t[0] in ["formalisms/SimpleClassDiagrams", "formalisms/Bottom"]
+            assert t[1] != None
+            assert t[2] == None
+
+        # Add a second bottom relation
+        conformance_add("users/user/test/a", "formalisms/Bottom")
+
+        # And remove the one without model, to make sure that it is not a wildcard!
+        conformance_delete("users/user/test/a", "formalisms/Bottom", "")
+
+        ts = model_types("users/user/test/a")
+        assert len(ts) == 2
+        while ts:
+            t = ts.pop()
+            assert t[0] in ["formalisms/SimpleClassDiagrams", "formalisms/Bottom"]
+            assert t[1] != None
+            assert t[2] == None
+
+        # Add again, but now remove the one with type mapping
+        conformance_add("users/user/test/a", "formalisms/Bottom")
+        
+        # First try one that doesn't match...
+        conformance_delete("users/user/test/a", "formalisms/Bottom", "NOTHING")
+
+        ts = model_types("users/user/test/a")
+        assert len(ts) == 3
+        while ts:
+            t = ts.pop()
+            assert t[0] in ["formalisms/SimpleClassDiagrams", "formalisms/Bottom"]
+            assert t[2] == None
+
+        # Now try one with the actual name
+        actual_name = [i for i in model_types("users/user/test/a") if i[0] == "formalisms/Bottom" and i[1] != None][0]
+
+        assert len(model_types("users/user/test/a")) == 3
+        conformance_delete("users/user/test/a", "formalisms/SimpleClassDiagrams", actual_name)
+        # Nothing removed, because of wrong TM model
+        assert len(model_types("users/user/test/a")) == 3
+
+        # Now remove correct one
+        conformance_delete("users/user/test/a", "formalisms/Bottom", actual_name)
+        ts = model_types("users/user/test/a")
+        assert len(ts) == 2
+        while ts:
+            t = ts.pop()
+            assert t[0] in ["formalisms/SimpleClassDiagrams", "formalisms/Bottom"]
+            if t[0] == "formalisms/SimpleClassDiagrams":
+                assert t[1] != None
+            elif t[1] == "formalisms/Bottom":
+                # Type mapping is empty
+                assert t[1] == None
+            assert t[2] == None
+
+
+        # Check add of non-existing model
+        try:
+            conformance_add("users/user/test/b", "formalisms/Bottom")
+            self.fail()
+        except UnknownModel:
+            pass
+
+        # Check add of non-existing metamodel
+        model_add("users/user/test/b", "formalisms/SimpleClassDiagrams")
+        before = model_types("users/user/test/b")
+        try:
+            conformance_add("users/user/test/b", "formalisms/Bottom2")
+            self.fail()
+        except UnknownModel:
+            assert model_types("users/user/test/b") == before
     """
     def test_op_model_render(self):
     def test_op_transformation_between(self):
@@ -3092,7 +3230,6 @@ class TestModelverse(unittest.TestCase):
     def test_op_transformation_execute_MANUAL(self):
     def test_op_transformation_signature(self):
     def test_op_process_signature(self):
-    def test_op_conformance_delete(self):
     """
 
     def test_modelling(self):

+ 1 - 1
wrappers/classes/modelverse.xml

@@ -901,7 +901,7 @@
                     <state id="conformance_delete">
                         <onentry>
                             <raise event="request">
-                                <parameter expr="['remove_conformance', self.parameters[0], self.parameters[1]]"/>
+                                <parameter expr="['remove_conformance', self.parameters[0], self.parameters[1], self.parameters[2]]"/>
                             </raise>
                         </onentry>
 

+ 2 - 2
wrappers/modelverse.py

@@ -413,8 +413,8 @@ def admin_demote(user_name):
     INPUT("admin_demote", [user_name])
     return OUTPUT()
 
-def conformance_delete(model_name, metamodel_name):
-    INPUT("conformance_delete", [model_name, metamodel_name])
+def conformance_delete(model_name, metamodel_name, type_mapping_name):
+    INPUT("conformance_delete", [model_name, metamodel_name, type_mapping_name])
     return OUTPUT()
 
 def conformance_add(model_name, metamodel_name):

+ 1 - 1
wrappers/modelverse_SCCD.py

@@ -2109,7 +2109,7 @@ class Modelverse(RuntimeClassBase):
         self.raiseInternalEvent(Event("request", None, [['admin_demote', self.parameters[0]]]))
     
     def _initialized_behaviour_operations_conformance_delete_enter(self):
-        self.raiseInternalEvent(Event("request", None, [['remove_conformance', self.parameters[0], self.parameters[1]]]))
+        self.raiseInternalEvent(Event("request", None, [['remove_conformance', self.parameters[0], self.parameters[1], self.parameters[2]]]))
     
     def _initialized_behaviour_operations_conformance_add_enter(self):
         self.raiseInternalEvent(Event("request", None, [['add_conformance', self.parameters[0], self.parameters[1]]]))