123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- 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
- Element src_model_model
- Element dst_model_model
- src_model_model = src_model["model"]
- reverse = make_reverse_dictionary(src_model_model)
- dst_model = instantiate_model(src_model["metamodel"])
- dst_model_model = dst_model["model"]
- 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
- Element model_model
- 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)
- model_model = model["model"]
- 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!
|