include "primitives.alh" include "object_operations.alh" include "typing.alh" 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 // Start of with some initialization Element tm Element elems String elem tm = get_type_mapping_as_dict(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(dict_in(model["model"], elem))): // Remove the key, as the model does not contain the element anymore dict_delete(tm, elem) else: 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 // TODO this must be expanded for other things than trivial metamodels! if (dict_len(model["model"]) > dict_len(tm)): // 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 elems String elem Element nodes Element edges nodes = allInstances(model["metamodel"], "Class") edges = allInstances(model["metamodel"], "Association") // Filter out classes from the associations Element new_nodes String node new_nodes = set_create() while (set_len(nodes) > 0): node = set_pop(nodes) if (bool_not(is_edge(model["metamodel"]["model"][node]))): set_add(new_nodes, node) nodes = new_nodes log("Nodes: " + set_to_string(nodes)) log("Edges: " + set_to_string(edges)) // Simple allocation: this seems like conformance bottom if (bool_and(set_len(edges) == 1, set_len(nodes) == 1)): String node_source_element String edge_element node_source_element = set_pop(nodes) edge_element = set_pop(edges) elems = dict_keys(model["model"]) while (set_len(elems) > 0): elem = set_pop(elems) if (is_edge(model["model"][elem])): retype(model, elem, edge_element) else: retype(model, elem, node_source_element) return True! // Simple allocation: this seems like a traceability model or so // Make sure to check that the edge goes from one node to the other! if (bool_and(set_len(edges) == 1, set_len(nodes) == 2)): String node_target_element String node_source_element String edge_element edge_element = set_pop(edges) 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("Could not automatically deduce mapping in a trivial way!") return False! elems = dict_keys(model["model"]) while (set_len(elems) > 0): elem = set_pop(elems) if (bool_and(is_edge(model["model"][elem]), read_nr_out(model["model"][elem]) == 0)): // An edge, and there is always exactly one, so type retype(model, elem, edge_element) // The source and target are ALWAYS typed as well! retype(model, readAssociationSource(model, elem), node_source_element) retype(model, readAssociationDestination(model, elem), node_target_element) return True! // Simple allocation: this seems like a dictionary model or so if (bool_and(set_len(edges) == 2, set_len(nodes) == 3)): String main_edge String small_edge main_edge = set_pop(edges) small_edge = set_pop(edges) if (readAssociationSource(model["metamodel"], main_edge) == small_edge): // Switch both String tmp tmp = main_edge main_edge = small_edge small_edge = tmp if (readAssociationSource(model["metamodel"], small_edge) == main_edge): String origin String value String key String middle_edge origin = readAssociationSource(model["metamodel"], main_edge) value = readAssociationDestination(model["metamodel"], main_edge) key = readAssociationDestination(model["metamodel"], small_edge) if (bool_and(bool_and(origin != value, origin != key), value != key)): // All three nodes are different, meaning that we are complete and have identified a simple mapping! elems = dict_keys(model["model"]) while (set_len(elems) > 0): elem = set_pop(elems) if (bool_and(is_edge(model["model"][elem]), read_nr_out(model["model"][elem]) == 0)): // An edge with no outgoing links, meaning that it is the small_edge retype(model, elem, small_edge) // Source is main_edge and target is key middle_edge = readAssociationSource(model, elem) retype(model, middle_edge, main_edge) retype(model, readAssociationDestination(model, elem), key) // The main_edge goes from root to the value retype(model, readAssociationSource(model, middle_edge), origin) retype(model, readAssociationDestination(model, middle_edge), value) return True! log("Could not automatically deduce mapping in a trivial way!") log("Model: " + set_to_string(dict_keys(model["model"]))) log("TM: " + set_to_string(dict_keys(tm))) log("DIFF: " + set_to_string(set_difference(dict_keys(model["model"]), dict_keys(tm)))) return False! return True!