123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- 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
- Element diff
- tm = get_type_mapping_as_dict(model)
- // 1a) remove elements from type mapping that are not in the model
- Element reverse
- reverse = make_reverse_dictionary_multi(tm)
- elems = dict_keys(reverse)
- diff = set_difference(elems, dict_keys(model["metamodel"]["model"]))
- while (set_len(diff) > 0):
- elems = reverse[set_pop(diff)]
- while (set_len(elems) > 0):
- dict_delete(tm, set_pop(elems))
- // 1b) remove elements from type mapping that are not in the model
- elems = dict_keys(tm)
- if (bool_not(set_equality(elems, dict_keys(model["model"])))):
- // First do a simplified check to see which ones are known to be there
- diff = set_difference(elems, dict_keys(model["model"]))
- while (set_len(diff) > 0):
- elem = set_pop(diff)
- 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)):
- if (set_len(set_difference(dict_keys(model["model"]), dict_keys(tm))) > 0):
- // 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!
|