include "primitives.alh" include "io.alh" include "object_operations.alh" include "constructors.alh" include "metamodels.alh" include "library.alh" include "modelling.alh" include "utils.alh" Element function model_fuse(models : Element): Element new_model Element tagged_model String model_name Element model Element keys Element second_keys String key Element selected_MM String type Element reverse Integer prev_length // Read out some data first if (set_len(models) == 0): log("Cannot fuse empty set of models!") return read_root()! tagged_model = set_read(models) new_model = instantiate_model(tagged_model[1]["metamodel"]) // Do the iteration while (set_len(models) > 0): tagged_model = set_pop(models) model_name = string_join(list_read(tagged_model, 0), "/") model = list_read(tagged_model, 1) reverse = make_reverse_dictionary(model["model"]) // Add all elements from 'model', but prepend it with the 'model_name' keys = dict_keys(model["model"]) second_keys = set_create() prev_length = -1 while (set_len(keys) > 0): key = set_pop(keys) type = read_type(model, key) if (is_edge(model["model"][key])): String src String dst src = string_join(model_name, reverse[cast_id(read_edge_src(model["model"][key]))]) dst = string_join(model_name, reverse[cast_id(read_edge_dst(model["model"][key]))]) if (bool_and(dict_in(new_model["model"], src), dict_in(new_model["model"], dst))): instantiate_link(new_model, type, model_name + key, src, dst) else: set_add(second_keys, key) elif (has_value(model["model"][key])): instantiate_value(new_model, type, model_name + key, model["model"][key]) else: instantiate_node(new_model, type, model_name + key) if (set_len(keys) == 0): if (set_len(second_keys) == prev_length): log("Cannot terminate model_fuse due to infinite recursion!") return read_root()! keys = second_keys second_keys = set_create() prev_length = set_len(keys) return new_model! Element function model_copy(src_model : Element): Element dst_model Element name Element keys Element second_keys String type Integer prev_length Element reverse reverse = make_reverse_dictionary(src_model["model"]) dst_model = instantiate_model(src_model["metamodel"]) keys = dict_keys(src_model["model"]) second_keys = set_create() prev_length = -1 while (set_len(keys) > 0): name = set_pop(keys) if (is_edge(src_model["model"][name])): // Is an edge, so potentially queue it String src String dst src = reverse[cast_id(read_edge_src(src_model["model"][name]))] dst = reverse[cast_id(read_edge_dst(src_model["model"][name]))] type = read_type(src_model, name) if (bool_and(dict_in(dst_model["model"], src), dict_in(dst_model["model"], dst))): // All present, so create the link between them instantiate_link(dst_model, type, name, src, dst) else: set_add(second_keys, name) elif (has_value(src_model["model"][name])): // Has a value, so copy that as well type = read_type(src_model, name) instantiate_value(dst_model, type, name, src_model["model"][name]) else: // Is a node type = read_type(src_model, name) instantiate_node(dst_model, type, name) if (set_len(keys) == 0): if (set_len(second_keys) == prev_length): log("Cannot terminate model_copy due to infinite recursion!") return read_root()! keys = second_keys second_keys = set_create() prev_length = set_len(keys) return dst_model! Element function model_join(models : Element, metamodel : Element, tracability_model : Element): Element new_model Element tagged_model String retyping_key Element elem_map Element model Element keys String new_name Element second_keys String src String dst String key String type Integer prev_length new_model = instantiate_model(metamodel) elem_map = dict_create() Element retyping_keys retyping_keys = set_create() // Do the iteration while (set_len(models) > 0): tagged_model = set_pop(models) retyping_key = string_join(list_read(tagged_model, 0), "/") model = list_read(tagged_model, 1) set_add(retyping_keys, retyping_key) // Add all elements from 'model' keys = dict_keys(model["model"]) second_keys = set_create() prev_length = -1 while (set_len(keys) > 0): // Copy the new element key = set_pop(keys) type = read_type(model, key) new_name = retyping_key + key if (is_edge(model["model"][key])): src = cast_id(read_edge_src(model["model"][key])) dst = cast_id(read_edge_dst(model["model"][key])) if (bool_and(dict_in(elem_map, src), dict_in(elem_map, dst))): new_name = instantiate_link(new_model, retyping_key + type, new_name, elem_map[src], elem_map[dst]) else: set_add(second_keys, key) new_name = "" elif (has_value(model["model"][key])): new_name = instantiate_value(new_model, retyping_key + type, new_name, model["model"][key]) else: new_name = instantiate_node(new_model, retyping_key + type, new_name) if (new_name != ""): // Add the new name to a map which registers the mapping to the new name dict_add_fast(elem_map, cast_id(model["model"][key]), new_name) if (set_len(keys) == 0): if (set_len(second_keys) == prev_length): log("Cannot terminate model_join due to infinite recursion!") return read_root()! keys = second_keys second_keys = set_create() prev_length = set_len(keys) // Now link in the tracability model // Go over all TracabilityLink elements and connect them in the merged model as well if (element_neq(tracability_model, read_root())): Element tracability_links String tracability_link String new_name_src String new_name_dst String src_name String dst_name Element src_models String src_model Element dst_models String dst_model tracability_links = allInstances(tracability_model, "TracabilityLink") while (set_len(tracability_links) > 0): tracability_link = set_pop(tracability_links) src_name = read_attribute(tracability_model, readAssociationSource(tracability_model, tracability_link), "name") dst_name = read_attribute(tracability_model, readAssociationDestination(tracability_model, tracability_link), "name") type = read_attribute(tracability_model, tracability_link, "type") // Now try to find all possible combinations // that is, find all models for which src_name exists, and all models for which dst_name exists, and connect them src_models = set_copy(retyping_keys) while (set_len(src_models) > 0): src_model = set_pop(src_models) if (dict_in(new_model["model"], src_model + src_name)): // This element exists for this source model dst_models = set_copy(retyping_keys) while (set_len(dst_models) > 0): dst_model = set_pop(dst_models) if (dict_in(new_model["model"], dst_model + dst_name)): // Found a match for source and target, so create a link new_name = instantiate_link(new_model, type, "", src_model + src_name, dst_model + dst_name) if (new_name == ""): log("ERROR: could not create a tracability link; ignoring") return new_model! Element function model_split(merged_model : Element, models : Element, tracability : Boolean): if (set_len(models) == 0): // No results needed, so stop immediately unless tracability is True if (bool_not(tracability)): return dict_create()! Element result Element metamodel Element model_tuple Element tracability_model Element keys String key String src String dst Element reverse Element mapping String retyping_key String original_type Element elem Element second_keys String type Element splitted String source String target String link String src_name String dst_name String new_name Integer prev_length result = dict_create() tracability_model = instantiate_model(import_node("models/Tracability")) reverse = make_reverse_dictionary(merged_model["model"]) mapping = dict_create() second_keys = set_create() prev_length = -1 while (set_len(models) > 0): model_tuple = set_pop(models) retyping_key = model_tuple[0] metamodel = model_tuple[1] dict_add_fast(result, retyping_key, instantiate_model(metamodel)) keys = dict_keys(merged_model["model"]) while (set_len(keys) > 0): key = set_pop(keys) elem = merged_model["model"][key] type = read_type(merged_model, key) splitted = string_split_nr(type, "/", 1) if (list_len(splitted) == 1): // Only one, so no split possible // Indicates a tracability element! if (bool_and(tracability, is_edge(elem))): // Got a tracability link! // Is always an edge (for now?) // Find out source and target and hope that they are already present src = reverse[cast_id(read_edge_src(elem))] dst = reverse[cast_id(read_edge_dst(elem))] // All present, so create the link between them src_name = list_pop_final(string_split_nr(src, "/", 1)) dst_name = list_pop_final(string_split_nr(dst, "/", 1)) source = instantiate_node(tracability_model, "Reference", "") target = instantiate_node(tracability_model, "Reference", "") instantiate_attribute(tracability_model, source, "name", src_name) instantiate_attribute(tracability_model, target, "name", dst_name) link = instantiate_link(tracability_model, "TracabilityLink", "", source, target) instantiate_attribute(tracability_model, link, "type", type) else: retyping_key = splitted[0] if (list_len(string_split(key, "/")) > 1): new_name = list_read(string_split_nr(key, "/", 1), 1) else: new_name = key if (dict_in(result, retyping_key)): original_type = splitted[1] if (is_edge(elem)): // Is an edge, so potentially queue it src = reverse[cast_id(read_edge_src(elem))] dst = reverse[cast_id(read_edge_dst(elem))] if (bool_and(dict_in(mapping, src), dict_in(mapping, dst))): // All present, so create the link between them // Though we first check the model to which it was mapped, as this should be the same as we have now if (bool_and(dict_in(result[retyping_key]["model"], mapping[src]), dict_in(result[retyping_key]["model"], mapping[dst]))): // The matching worked fine dict_add_fast(mapping, key, instantiate_link(result[retyping_key], original_type, new_name, mapping[src], mapping[dst])) else: log("ERROR mapping: source/target mapped to model, but not found in expected model; ignoring") else: // Still source or destination in the queue, so we wait for that set_add(second_keys, key) elif (has_value(elem)): // Has a value, so copy that as well dict_add_fast(mapping, key, instantiate_value(result[retyping_key], original_type, new_name, elem)) else: // Is a node dict_add_fast(mapping, key, instantiate_node(result[retyping_key], original_type, new_name)) if (set_len(keys) == 0): if (set_len(second_keys) == prev_length): log("Cannot terminate model_split due to infinite recursion!") return read_root()! keys = second_keys second_keys = set_create() prev_length = set_len(keys) // Finally, we also add tracability information as a separate model if (tracability): dict_add_fast(result, "__tracability", tracability_model) log("Tracability model created with # links = " + cast_value(dict_len(tracability_model["model"]))) return result!