Browse Source

Significant bugfixes for conformance relation: added type mapping MM, add conformance_finding algorithm that deduces a type mapping automatically for type mapping models

Yentl Van Tendeloo 7 years ago
parent
commit
3cdc651ed9

+ 40 - 22
bootstrap/conformance_finding.alc

@@ -44,46 +44,64 @@ Boolean function find_type_mapping(model : Element):
 		Element elems
 		String elem
 
-		String node_element
+		String node_source_element
+		String node_target_element
 		String edge_element
-		node_element = read_root()
-		edge_element = read_root()
 
 		Element nodes
 		Element edges
 		nodes = allInstances(model["metamodel"], "Class")
 		edges = allInstances(model["metamodel"], "Association")
 
-		if (set_len(nodes) > 1):
-			log("Got nodes: " + set_to_string(nodes))
-			log("Multiple nodes detected!")
-			return False!
-		elif (set_len(edges) > 1):
-			log("Got edges: " + set_to_string(edges))
-			log("Multiple edges detected!")
-			return False!
-		elif (set_len(nodes) != 1):
-			log("No node found!")
-			return False!
-		elif (set_len(edges) != 1):
-			log("No edge found!")
-			return False!
-		else:
-			node_element = set_pop(nodes)
+		log("Searching for type...")
+		if (bool_and(set_len(edges) == 1, set_len(nodes) == 1)):
+			// Simple allocation: this seems like conformance bottom
+			node_source_element = set_pop(nodes)
+			node_target_element = node_source_element
+			edge_element = set_pop(edges)
+			log("Found node: " + node_source_element)
+			log("Found edge: " + edge_element)
+
+		elif (bool_and(set_len(edges) == 1, set_len(nodes) == 2)):
+			// Simple allocation: this seems like a type mapping
+			// Make sure to check that the edge goes from one node to the other!
 			edge_element = set_pop(edges)
-			log("Found node: " + node_element)
+			node_source_element = readAssociationSource(model["metamodel"], edge_element)
+			node_target_element = readAssociationDestination(model["metamodel"], edge_element)
+
+			if (value_eq(node_source_element, node_target_element)):
+				log("Source and target are the same, meaning that the second node is unknown")
+				return False!
+
 			log("Found edge: " + edge_element)
+			log("Found source node: " + node_source_element)
+			log("Found target node: " + node_target_element)
+
+		else:
+			log("Could not automatically deduce mapping in a trivial way!")
+			return False!
+
 
-		// Now we have bot an edge_element and node_element of the metamodel
+		// Now we have both an edge_element and node_element of the metamodel
 		// Now just trivially bind all elements!
+		log("Searching for type...")
 		elems = dict_keys(model["model"])
 		while (set_len(elems) > 0):
 			elem = set_pop(elems)
 
 			if (is_edge(model["model"][elem])):
+				// An edge, and there is always exactly one, so type
 				retype(model, elem, edge_element)
+			elif (node_source_element == node_target_element):
+				// A node, and we are sure that there is only one
+				retype(model, elem, node_source_element)
 			else:
-				retype(model, elem, node_element)
+				// We have an element and know that there is an edge connecting them
+				// If there is an outgoing link, we make it "node_target_element", otherwise "node_source_element"
+				if (read_nr_out(model["model"][elem]) > 0):
+					retype(model, elem, node_source_element)
+				else:
+					retype(model, elem, node_target_element)
 
 	// 3) (optional) verify that the mapping is correct with conformance checking
 	// TODO

+ 5 - 4
bootstrap/core_algorithm.alc

@@ -111,6 +111,7 @@ Element function get_full_model(model_id : String, metamodel_id : String):
 		Element mm
 		mm = get_full_model(metamodel_id, get_entry_id("formalisms/SimpleClassDiagrams"))
 		if (element_eq(mm, read_root())):
+			log("Error finding type mapping...")
 			return read_root()!
 		else:
 			dict_add(m, "metamodel", mm)
@@ -2340,14 +2341,14 @@ String function cmd_model_types(model_name : String):
 		model_id = get_entry_id(model_name)
 
 		Element types
-		String type
+		String type_link
 		String result
 
 		result = "Success: "
-		types = allAssociationDestinations(core, model_id, "instanceOf")
+		types = allOutgoingAssociationInstances(core, model_id, "instanceOf")
 		while (set_len(types) > 0):
-			type = set_pop(types)
-			result = string_join(result, full_name(type) + "\n")
+			type_link = set_pop(types)
+			result = result + full_name(readAssociationDestination(core, type_link)) + ", " + full_name(set_pop(allAssociationDestinations(core, type_link, "typing"))) + ", " + full_name(set_pop(allAssociationDestinations(core, type_link, "semantics")))+ "\n"
 
 		return result!
 	else:

+ 9 - 0
bootstrap/type_mapping.mvc

@@ -0,0 +1,9 @@
+import models/SimpleClassDiagrams as SCD
+
+SCD type_mapping {
+    Class Instance {}
+    Class Type {}
+    Association TypeLink (Instance, Type) {}
+}
+
+export type_mapping to models/TypeMapping

+ 1 - 1
wrappers/classes/modelverse.xml

@@ -938,7 +938,7 @@
 
                         <transition cond="self.expect_response_partial('Success: ')" target="../../wait_for_action/history">
                             <raise event="result">
-                                <parameter expr="set(self.split_response(self.responses.pop(0)))"/>
+                                <parameter expr="set([tuple(i.split(', ')) for i in self.split_response(self.responses.pop(0))])"/>
                             </raise>
                         </transition>
                     </state>

+ 2 - 2
wrappers/modelverse.py

@@ -239,8 +239,8 @@ def model_list_full(location):
     INPUT("model_list_full", [location])
     return OUTPUT()
 
-def verify(model_name, metamodel_name):
-    INPUT("verify", [model_name, metamodel_name])
+def verify(model_name, metamodel_name, conformance_function=""):
+    INPUT("verify", [model_name, metamodel_name, conformance_function])
     return OUTPUT()
 
 def model_overwrite(model_name, new_model):

+ 2 - 2
wrappers/modelverse_SCCD.py

@@ -1,7 +1,7 @@
 """
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 
-Date:   Thu May 24 11:42:22 2018
+Date:   Thu May 24 16:50:33 2018
 
 Model author: Yentl Van Tendeloo
 Model name:   MvK Server
@@ -2836,7 +2836,7 @@ class Modelverse(RuntimeClassBase):
         return self.expect_response('Success')
     
     def _initialized_behaviour_operations_model_types_0_exec(self, parameters):
-        self.raiseInternalEvent(Event("result", None, [set(self.split_response(self.responses.pop(0)))]))
+        self.raiseInternalEvent(Event("result", None, [set([tuple(i.split(', ')) for i in self.split_response(self.responses.pop(0))])]))
     
     def _initialized_behaviour_operations_model_types_0_guard(self, parameters):
         return self.expect_response_partial('Success: ')