include "primitives.alh" include "conformance_scd.alh" include "constructors.alh" include "modelling.alh" Element function allInstances(model : Element, type_name : String): Element result Element type String key Element keys keys = dict_keys(model["model"]) type = model["metamodel"]["model"][type_name] result = create_node() // TODO more efficient to work backwards: find all instances of an element through the type mapping directly // must then take into account all inheritance links ourselves... while (0 < list_len(keys)): key = set_pop(keys) if (is_nominal_instance(model, key, type_name)): set_add(result, key) return result! Element function selectPossibleIncoming(model : Element, target : String, limit_set : Element): // Find all possible incoming link types for the target model // Should also include those specified on the superclass(es) String type Element model_dict Element elem Element result Element target_element result = create_node() model_dict = model["model"] while (0 < list_len(limit_set)): type = set_pop(limit_set) elem = model_dict[type] if (is_nominal_subtype(model, target, reverseKeyLookup(model_dict, read_edge_dst(elem)))): set_add(result, type) return result! Element function selectPossibleOutgoing(model : Element, source : String, limit_set : Element): // Find all possible outgoing link types for the source model // Should also include those specified on the superclass(es) String type Element model_dict Element elem Element result Element source_element result = create_node() model_dict = model["model"] while (0 < list_len(limit_set)): type = set_pop(limit_set) elem = model_dict[type] if (is_nominal_subtype(model, source, reverseKeyLookup(model_dict, read_edge_src(elem)))): set_add(result, type) return result! Element function allOutgoingAssociationInstances(model : Element, source_name : String, assoc_name : String): // Read out all outgoing edges of the model and select those that are typed by the specified association Element result Element source String option Integer all_out Integer i result = create_node() source = model["model"][source_name] all_out = read_nr_out(source) i = 0 while (i < all_out): option = reverseKeyLookup(model["model"], read_out(source, i)) if (is_nominal_instance(model, option, assoc_name)): set_add(result, option) i = i + 1 return result! Element function allIncomingAssociationInstances(model : Element, target_name : String, assoc_name : String): // Read out all outgoing edges of the model and select those that are typed by the specified association Element assocs String assoc Element result Element target assocs = allInstances(model, assoc_name) target = model["model"][target_name] result = create_node() while (0 < list_len(assocs)): assoc = set_pop(assocs) if (element_eq(target, read_edge_dst(model["model"][assoc]))): set_add(result, assoc) return result! Element function getAttributeList(model : Element, element : String): Element result Element keys Element type Element attr_name Element types String attr_type result = create_node() types = get_superclasses(model["metamodel"], read_type(model, element)) while (read_nr_out(types) > 0): type = set_pop(types) keys = dict_keys(model["metamodel"]["model"][type]) // Add our own attributes while (0 < list_len(keys)): attr_name = set_pop(keys) if (is_physical_string(attr_name)): attr_type = reverseKeyLookup(model["metamodel"]["model"], model["metamodel"]["model"][type][attr_name]) dict_add(result, attr_name, attr_type) return result! Element function getInstantiatableAttributes(model : Element, element : String): Element result result = create_node() Element types types = get_superclasses(model, element) while (read_nr_out(types) > 0): element = set_pop(types) // Get all outgoing "dictionary" links Element set_own Element elem elem = model["model"][element] set_own = dict_keys(elem) // Filter them Element e while (0 < read_nr_out(set_own)): e = set_pop(set_own) if (is_physical_string(e)): dict_add(result, e, reverseKeyLookup(model["model"], elem[e])) return result! String function reverseKeyLookup(dict : Element, element : Element): Integer nr_in Integer nr_out Integer counter Element link nr_in = read_nr_in(element) counter = 0 while (counter < nr_in): if (element_eq(read_edge_src(read_in(element, counter)), dict)): // Got a match return (read_edge_dst(read_out(read_in(element, counter), 0)))! counter = counter + 1 return string_join(string_join("(unknown: ", cast_e2s(element)), " )")! String function print_dict(dict : Element): Element keys Element key String result keys = dict_keys(dict) result = "" while (0 < list_len(keys)): key = set_pop(keys) result = result + cast_v2s(key) result = result + ": " result = result + cast_v2s(dict[key]) result = result + "\n" return result! String function readAssociationSource(model : Element, name : String): return reverseKeyLookup(model["model"], read_edge_src(model["model"][name]))! String function readAssociationDestination(model : Element, name : String): return reverseKeyLookup(model["model"], read_edge_dst(model["model"][name]))! String function followAssociation(model : Element, element_name : String, association_name : String): Element assocs String assoc Element result assocs = allOutgoingAssociationInstances(model, element_name, association_name) result = create_node() while (0 < list_len(assocs)): set_add(result, readAssociationDestination(model, set_pop(assocs))) return result! Element function allAssociationDestinations(model : Element, name : String, association_type : String): Element tmp Element result result = create_node() tmp = allOutgoingAssociationInstances(model, name, association_type) while (read_nr_out(tmp) > 0): set_add(result, readAssociationDestination(model, set_pop(tmp))) return result! Element function allowedAssociationsBetween(model : Element, src : String, dst : String): // Go to the type and find all possibilities String type Element all_types Integer nr_edges Integer i Element result Element edge String edge_name String dst_name result = create_node() type = read_type(model, src) all_types = get_superclasses(model["metamodel"], type) while (read_nr_out(all_types) > 0): type = set_pop(all_types) nr_edges = read_nr_out(model["metamodel"]["model"][type]) i = 0 while (i < nr_edges): edge = read_out(model["metamodel"]["model"][type], i) if (set_in(model["metamodel"]["model"], edge)): // Find destination dst_name = reverseKeyLookup(model["metamodel"]["model"], read_edge_dst(edge)) edge_name = reverseKeyLookup(model["metamodel"]["model"], edge) if (is_nominal_instance(model, dst, dst_name)): // Find out whether our dst is an instance of the found destination type set_add(result, edge_name) i = i + 1 return result! String function read_type(model : Element, name : String): String result Element tm if (dict_in(model["model"], name)): if (dict_in(model["type_mapping"], name)): result = model["type_mapping"][name] if (dict_in(model["metamodel"]["model"], result)): return result! else: log("Could not find " + result) return ""! else: log("Untyped " + name) log("Type mapping: " + dict_to_string(model["type_mapping"])) return ""! else: log("Couldn't find type of " + name) return ""!