Browse Source

Update to type finding

Yentl Van Tendeloo 8 years ago
parent
commit
09decf267a

+ 57 - 28
bootstrap/conformance_finding.alc

@@ -2,44 +2,73 @@ include "primitives.alh"
 include "object_operations.alh"
 include "typing.alh"
 
-Element function find_type_mapping(model : Element, metamodel : Element):
-	// Takes as input a model dictionary and fully specified metamodel
-	// No other entries are required, and the type mapping is returned
+Boolean function find_type_mapping(model : Element):
+	// Finds a correct type mapping for the provided model (with partial type mapping)
+	// We go through several phases:
+	//   1) remove elements from type mapping that are not in the model or metamodel
+	//   2) find a mapping based on the current partial mapping
+	//   3) (optional) verify that the mapping is correct with conformance checking
+	// Returns True if the type mapping was altered
 
-	// TODO for now, this only returns something for a simple case, where the MM has one edge, and one node
-	//      and it makes the assumption that SCD is the M3 level...
-
-	// First find the name of the edge and node elements
-	Element result
+	// Start of with some initialization
+	Boolean result
+	Element tm
 	Element elems
 	String elem
 
-	String node_element
-	String edge_element
+	result = False
+	tm = get_type_mapping_as_dict(model)
 
-	elems = dict_keys(metamodel["model"])
+	// 1) remove elements from type mapping that are not in the model or metamodel
+	elems = dict_keys(tm)
 	while (set_len(elems) > 0):
 		elem = set_pop(elems)
-
-		if (bool_not(is_edge(elem))):
-			node_element = elem
+		if (bool_not(dict_in(model["model"], elem))):
+			// Remove the key, as the model does not contain the element anymore
+			dict_delete(tm, elem)
 		else:
-			// Is an edge, but might be the inheritance link...
-			if (read_type(metamodel, elem) != "Inheritance"):
-				// Is not the inheritance link
-				edge_element = elem
+			if (bool_not(dict_in(model["metamodel"]["model"], tm[elem]))):
+				// Remove the key, as the metamodel does not contain the type anymore
+				dict_delete(tm, elem)
+		
+	// 2) find a mapping based on the current partial mapping, but only if it is not yet complete
+	if (dict_len(model["model"]) > dict_len(tm)):
+		result = True
+		// TODO for now, this only returns something for a simple case, where the MM has one edge, and one node
+		//      and it makes the assumption that SCD is the M3 level...
 
-	// Now we have bot an edge_element and node_element of the metamodel
-	// Now just trivially bind all elements!
-	result = create_node()
+		// First find the name of the edge and node elements
+		Element elems
+		String elem
 
-	elems = dict_keys(model)
-	while (set_len(elems) > 0):
-		elem = set_pop(elems)
+		String node_element
+		String edge_element
 
-		if (is_edge(elem)):
-			dict_add(result, elem, edge_element)
-		else:
-			dict_add(result, elem, node_element)
+		elems = dict_keys(model["metamodel"]["model"])
+		while (set_len(elems) > 0):
+			elem = set_pop(elems)
+
+			if (bool_not(is_edge(elem))):
+				node_element = elem
+			else:
+				// Is an edge, but might be the inheritance link...
+				if (read_type(model["metamodel"]["model"], elem) != "Inheritance"):
+					// Is not the inheritance link
+					edge_element = elem
+
+		// Now we have bot an edge_element and node_element of the metamodel
+		// Now just trivially bind all elements!
+		elems = dict_keys(model["model"])
+		while (set_len(elems) > 0):
+			elem = set_pop(elems)
+
+			if (is_edge(elem)):
+				retype(model, elem, edge_element)
+			else:
+				retype(model, elem, node_element)
+
+	// 3) (optional) verify that the mapping is correct with conformance checking
+	// TODO
+	// If not, set the result to read_root()
 	
 	return result!

+ 43 - 10
bootstrap/core_algorithm.alc

@@ -40,9 +40,7 @@ String function get_instanceOf_link(model_id : String, metamodel_id : String):
 	if (set_len(all_links) > 1):
 		log("WARNING: multiple instanceOf relations were detected for this model; picking one at random!")
 	elif (set_len(all_links) == 0):
-		log("ERROR: untyped model; crashing")
-		log("Instance model: " + cast_v2s(read_attribute(core, model_id, "name")))
-		log("Type model: " + cast_v2s(read_attribute(core, metamodel_id, "name")))
+		return read_root()!
 	
 	choice = set_pop(all_links)
 
@@ -58,15 +56,42 @@ Element function get_full_model(model_id : String, metamodel_id : String):
 
 	m = dict_create()
 	dict_add(m, "model", import_node(read_attribute(core, model_id, "location")))
-	dict_add(m, "type_mapping", import_node(read_attribute(core, set_pop(allAssociationDestinations(core, choice, "typing")), "location")))
-	dict_add(m, "semantics", set_pop(allAssociationDestinations(core, choice, "semantics")))
 
-	if (readAssociationDestination(core, choice) == model_id):
+	// TODO for now this is restricted to the fixed semantics
+	// dict_add(m, "semantics", set_pop(allAssociationDestinations(core, choice, "semantics")))
+	dict_add(m, "semantics", get_model_id("conformance_mv"))
+
+	if (metamodel_id == model_id):
 		// Found the meta-circular level, so we can stop!
 		dict_add(m, "metamodel", m)
 	else:
-		dict_add(m, "metamodel", get_full_model(readAssociationDestination(core, choice), get_model_id("SimpleClassDiagrams")))
-		
+		dict_add(m, "metamodel", get_full_model(metamodel_id, get_model_id("SimpleClassDiagrams")))
+
+	if (element_neq(choice, read_root())):
+		if (set_len(allAssociationDestinations(core, choice, "typing")) == 1):
+			// Add the preferred original type mapping
+			dict_add(m, "type_mapping", import_node(read_attribute(core, set_pop(allAssociationDestinations(core, choice, "typing")), "location")))
+		else:
+			// Start from scratch
+			dict_add(m, "type_mapping", new_type_mapping())
+	else:
+		// Start from scratch
+		dict_add(m, "type_mapping", new_type_mapping())
+	
+	// Perform corrections on the type mapping, based on the current knowledge
+	if (element_neq(choice, read_root())):
+		// There was an instanceOf link, but we can remove that one as we resolved the new type
+		model_delete_element(core, choice)
+
+	if (find_type_mapping(m)):
+		// Export the type_mapping that we found just now
+		if (element_neq(choice, read_root())):
+			// There was a previou one, which we remove now
+			model_delete_element(core, choice)
+
+		// Check if we could find a mapping
+		// TODO assume that we always can!
+
 	return m!
 
 Integer function get_relation_to_model(user_id : String, model_id : String):
@@ -1033,7 +1058,10 @@ String function cmd_model_list():
 	models = allInstances(core, "Model")
 	while (set_len(models) > 0):
 		m = set_pop(models)
-		result = (result + string_join((string_join("  ", read_attribute(core, m, "name")) + " : "), read_attribute(core, set_pop(allAssociationDestinations(core, m, "instanceOf")), "name"))) + "\n"
+		if (set_len(allAssociationDestinations(core, m, "instanceOf")) > 0):
+			result = (result + string_join((string_join("  ", read_attribute(core, m, "name")) + " : "), read_attribute(core, set_pop(allAssociationDestinations(core, m, "instanceOf")), "name"))) + "\n"
+		else:
+			result = result + string_join(string_join("  ", read_attribute(core, m, "name")), " : None\n")
 	return result!
 
 String function cmd_model_list_full():
@@ -1055,7 +1083,12 @@ String function cmd_model_list_full():
 		owner = read_attribute(core, set_pop(allAssociationDestinations(core, m, "owner")), "name")
 		group = read_attribute(core, set_pop(allAssociationDestinations(core, m, "group")), "name")
 		name = read_attribute(core, m, "name")
-		type = read_attribute(core, set_pop(allAssociationDestinations(core, m, "instanceOf")), "name")
+
+		if (set_len(allAssociationDestinations(core, m, "instanceOf")) > 0):
+			type = read_attribute(core, set_pop(allAssociationDestinations(core, m, "instanceOf")), "name")
+		else:
+			type = "None"
+
 		result = (result + ((((((((("  " + permissions) + " ") + owner) + " ") + group) + " ") + name) + " : ") + type)) + "\n"
 
 	return result!

+ 1 - 1
interface/HUTN/includes/conformance_finding.alh

@@ -1 +1 @@
-Element function find_type_mapping(model : Element, metamodel : Element)
+Boolean function find_type_mapping(model : Element)