include "primitives.alh" include "io.alh" include "object_operations.alh" include "constructors.alh" include "metamodels.alh" include "library.alh" include "modelling.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 // Read out some data first if (read_nr_out(models) == 0): log("Cannot fuse empty set of models!") return read_root()! tagged_model = set_pop(models) set_add(models, tagged_model) new_model = instantiate_model(tagged_model[1]["metamodel"]) // Do the iteration while (read_nr_out(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 = create_node() while (read_nr_out(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_id2s(read_edge_src(model["model"][key]))]) dst = string_join(model_name, reverse[cast_id2s(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 (read_nr_out(keys) == 0): keys = second_keys second_keys = create_node() return new_model! Element function model_copy(src_model : Element): Element dst_model Element name Element keys Element second_keys String type Element reverse reverse = make_reverse_dictionary(src_model["model"]) dst_model = instantiate_model(src_model["metamodel"]) keys = dict_keys(src_model["model"]) second_keys = create_node() while (read_nr_out(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_id2s(read_edge_src(src_model["model"][name]))] dst = reverse[cast_id2s(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 (read_nr_out(keys) == 0): keys = second_keys second_keys = create_node() return dst_model! Element function model_retype_on_name(model : Element, new_MM : Element, operation : String, name : String): String key String type Element keys Integer length keys = dict_keys(model["model"]) length = string_len(name) while (read_nr_out(keys) > 0): key = set_pop(keys) if (dict_in(model["model"], key)): // Check if the element is still there, as a delete of a node might remove all attached links automatically type = read_type(model, key) if (operation == "+"): // Keep all, but augment typename dict_delete(model["type_mapping"], key) dict_add_fast(model["type_mapping"], key, name + type) elif (operation == "-"): // Keep only if typename beginning matches and remove from typename if (string_startswith(type, name)): dict_delete(model["type_mapping"], key) dict_add_fast(model["type_mapping"], key, string_substr(type, length, string_len(type))) else: model_delete_element(model, key) dict_delete(model, "metamodel") dict_add_fast(model, "metamodel", new_MM) return 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 new_model = instantiate_model(metamodel) elem_map = create_node() // Do the iteration while (read_nr_out(models) > 0): tagged_model = set_pop(models) retyping_key = string_join(list_read(tagged_model, 0), "/") model = list_read(tagged_model, 1) // Add all elements from 'model' keys = dict_keys(model["model"]) second_keys = create_node() while (read_nr_out(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_id2s(read_edge_src(model["model"][key])) dst = cast_id2s(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_id2s(model["model"][key]), new_name) if (read_nr_out(keys) == 0): keys = second_keys second_keys = create_node() // 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 tracability_links = allInstances(tracability_model, "TracabilityLink") while (read_nr_out(tracability_links) > 0): tracability_link = set_pop(tracability_links) // Get necessary information from the tracability link new_name_src = elem_map[cast_id2s(read_edge_src(tracability_model["model"][tracability_link]))] new_name_dst = elem_map[cast_id2s(read_edge_dst(tracability_model["model"][tracability_link]))] type = read_attribute(tracability_model, tracability_link, "type") // Connect the two with the info we have new_name = instantiate_link(new_model, type, "", new_name_src, new_name_dst) 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 (read_nr_out(models) == 0): // No results needed, so stop immediately unless tracability is True if (bool_not(tracability)): return create_node()! 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 result = create_node() tracability_model = instantiate_model(import_node("models/Tracability")) reverse = make_reverse_dictionary(merged_model["model"]) mapping = create_node() second_keys = create_node() while (read_nr_out(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 (read_nr_out(keys) > 0): key = set_pop(keys) elem = merged_model["model"][key] type = read_type(merged_model, key) splitted = string_split(type, "/") 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_id2s(read_edge_src(elem))] dst = reverse[cast_id2s(read_edge_dst(elem))] src_name = list_read(string_split(read_type(merged_model, src), "/"), 0) dst_name = list_read(string_split(read_type(merged_model, dst), "/"), 0) // Check if we actually keep both models around, as otherwise it is useless anyway if (bool_and(dict_in(result, src_name), dict_in(result, dst_name))): if (bool_and(dict_in(mapping, src), dict_in(mapping, dst))): // All present, so create the link between them Element src_model Element dst_model src_model = result[src_name] dst_model = result[dst_name] source = reuse_element(tracability_model, "Reference", "", src_model["model"][mapping[src]]) target = reuse_element(tracability_model, "Reference", "", dst_model["model"][mapping[dst]]) link = instantiate_link(tracability_model, "TracabilityLink", "", source, target) instantiate_attribute(tracability_model, link, "type", type) else: // Not yet available! set_add(second_keys, key) else: retyping_key = splitted[0] if (read_nr_out(string_split(key, "/")) > 1): new_name = list_read(string_split(key, "/"), 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_id2s(read_edge_src(elem))] dst = reverse[cast_id2s(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 (read_nr_out(keys) == 0): keys = second_keys second_keys = create_node() // 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_v2s(read_nr_out(tracability_model["model"]))) return result!