include "primitives.alh" include "library.alh" include "object_operations.alh" include "constructors.alh" Element function set_copy(elem_to_copy : Element): Element result Integer counter_copy Integer max result = create_node() // Expand the provided list by including all elements that need to be checked counter_copy = 0 max = read_nr_out(elem_to_copy) while (integer_lt(counter_copy, max)): set_add(result, read_edge_dst(read_out(elem_to_copy, counter_copy))) counter_copy = integer_addition(counter_copy, 1) return result Boolean function is_direct_instance(model_idi : Element, instance_idi : Element, type_idi : Element): // Just check whether or not the type mapping specifies the type as the type of the instance return element_eq(dict_read_node(dict_read(model_idi, "type_mapping"), instance_idi), type_idi) Boolean function is_nominal_instance(model_ini : Element, instance_ini : Element, type_ini : Element): return is_nominal_subtype(type_ini, dict_read_node(dict_read(model_ini, "type_mapping"), instance_ini), dict_read(dict_read(model_ini, "metamodel"), "type_mapping"), dict_read(model_ini, "inheritance")) Boolean function is_nominal_subtype(superclass : Element, subclass : Element, types : Element, inheritance_link : Element): Integer counter_iso Integer i_iso Element edge_iso Element destination_iso // End of recursion if (element_eq(superclass, subclass)): return True // Iterate over all superclasses of the found class counter_iso = read_nr_out(subclass) i_iso = 0 while (integer_lt(i_iso, counter_iso)): edge_iso = read_out(subclass, i_iso) // Check if it even has a type (to prevent errors) if (dict_in_node(types, edge_iso)): // Check whether it is an inheritance edge, as there is no other distinction between them if (element_eq(dict_read_node(types, edge_iso), inheritance_link)): // It is an inheritance edge, so follow it to its destination destination_iso = read_edge_dst(edge_iso) // Found a new superclass to test if (is_nominal_subtype(superclass, destination_iso, types, inheritance_link)): return True i_iso = integer_addition(i_iso, 1) // No link seems to have been found, so it is False return False Boolean function is_structural_instance(model_isi : Element, instance_isi : Element, type_isi : Element): return is_structural_subtype(dict_read_node(dict_read(model_isi, "type_mapping"), instance_isi), type_isi) Boolean function is_structural_subtype(subtype_isi : Element, supertype_isi : Element): // Determine whether it is just the exact type or not if (element_eq(subtype_isi, supertype_isi)): return True // Find all links that are required (name and type) from the specified type Element required_keys_isi required_keys_isi = dict_keys(supertype_isi) Integer required_keys_len_isi required_keys_len_isi = dict_len(required_keys_isi) String key_isi Element equivalent_isi Integer i_isi i_isi = 0 // Go over all keys that we require while (integer_lt(i_isi, required_keys_len_isi)): key_isi = set_pop(required_keys_isi) // Check whether they exist in the instance if (dict_in(subtype_isi, key_isi)): // Normally, we should still check whether they don't violate the constraints imposed on the class (i.e., are actually present) // For now, we ignore this and simply require that it is always there in the metamodel (not necessarily in the instance) // TODO // Still check whether the types match if (bool_not(is_structural_subtype(dict_read(subtype_isi, key_isi), dict_read(supertype_isi, key_isi)))): return False // All clear, so pass on to the next attribute i_isi = integer_addition(i_isi, 1) else: return False // No violations found, so OK return True String function conformance_scd(model : Element): // Initialization Element work_conf Element model_src Element metamodel_src Element model_dst Element metamodel_dst Element models Element metamodels models = set_copy(dict_read(model, "model")) Element typing typing = dict_read(model, "type_mapping") metamodels = set_copy(dict_read(dict_read(model, "metamodel"), "model")) Element inheritance inheritance = dict_read(dict_read(model, "metamodel"), "inheritance") Element metamodel_typing metamodel_typing = dict_read(dict_read(model, "metamodel"), "type_mapping") // Iterate over all model elements and check if they are typed (in "typing") and their type is in the metamodel while (integer_gt(dict_len(models), 0)): work_conf = set_pop(models) // Basic check: does the element have a type if (bool_not(dict_in_node(typing, work_conf))): return string_join("Model has no type specified: ", getName(model, work_conf)) // Basic check: is the type of the element part of the metamodel if (bool_not(set_in_node(metamodels, dict_read_node(typing, work_conf)))): return string_join("Type of element not in specified metamodel: ", getName(model, work_conf)) // Basic check: type of the value agrees with the actual type // this is always checked, as it falls back to a sane default for non-values if (bool_not(type_eq(dict_read_node(typing, work_conf), typeof(work_conf)))): return string_join("Primitive type does not agree with actual type: ", getName(model, work_conf)) // For edges only: check whether the source is typed according to the metamodel if (is_edge(work_conf)): model_src = read_edge_src(work_conf) metamodel_src = read_edge_src(dict_read_node(typing, work_conf)) if (bool_not(is_nominal_instance(model, model_src, metamodel_src))): return string_join("Source of model edge not typed by source of type: ", getName(model, work_conf)) // For edges only: check whether the destination is typed according to the metamodel if (is_edge(work_conf)): model_dst = read_edge_dst(work_conf) metamodel_dst = read_edge_dst(dict_read_node(typing, work_conf)) if (bool_not(is_nominal_instance(model, model_dst, metamodel_dst))): return string_join("Destination of model edge not typed by destination of type: ", getName(model, work_conf)) // Structure seems fine, now do static semantics if (dict_in(dict_read(model, "metamodel"), "constraints")): Element constraint_function constraint_function = dict_read(dict_read(model, "metamodel"), "constraints") return constraint_function(model) else: return "OK" Element function retype(model_rt : Element, metamodel_rt : Element, inheritance_rt : Element, mapping_rt : Element): if (dict_in(model_rt, "type_mapping")): // Remove previous type mappings dict_delete(model_rt, "type_mapping") if (dict_in(model_rt, "metamodel")): // Remove the previous metamodel too, as this might change too dict_delete(model_rt, "metamodel") if (dict_in(model_rt, "inheritance")): // Remove the inheritance link too, as, yet again, this can vary dict_delete(model_rt, "inheritance") // Start the new configuration of the metamodel and inheritance link, as well as set the new mapping relation dict_add(model_rt, "metamodel", metamodel_rt) dict_add(model_rt, "inheritance", inheritance_rt) dict_add(model_rt, "type_mapping", mapping_rt) return model_rt Element function add_to_model(model_atm : Element, name_atm : String, element_atm : Element): if (string_eq(name_atm, "")): // No name desired dict_add(dict_read(model_atm, "model"), string_join("__", cast_id2s(element_atm)), element_atm) else: dict_add(dict_read(model_atm, "model"), name_atm, element_atm) return element_atm Element function instantiate_bottom_node(model_bn : Element, name_bn : String): Element new_element_bn new_element_bn = create_node() return add_to_model(model_bn, name_bn, new_element_bn) Element function instantiate_bottom_value(model_bv : Element, name_bv : String, value_bv : Element): Element new_element_bv new_element_bv = create_value(value_bv) return add_to_model(model_bv, name_bv, new_element_bv) Element function instantiate_bottom_edge(model_be : Element, name_be : String, source_be : Element, target_be : Element): Element new_element_be new_element_be = create_edge(source_be, target_be) return add_to_model(model_be, name_be, new_element_be) Element function set_model_constraints(model_con : Element, func_con : Element): if (dict_in(model_con, "constraints")): dict_delete(model_con, "constraints") dict_add(model_con, "constraints", func_con) return model_con Element function instantiate_model_lib(model_mo : Element, type_mo : Element, name_mo : String, optionals : Element, attribute_types : Element, attribute_instances : Element): Element new_element_mo if (is_edge(type_mo)): // Create a new edge from "optionals[0]" to "optionals[1]" new_element_mo = instantiate_bottom_edge(model_mo, name_mo, list_read(optionals, 0), list_read(optionals, 1)) else: if (type_eq(typeof(type_mo), Type)): new_element_mo = instantiate_bottom_value(model_mo, name_mo, list_read(optionals, 0)) else: new_element_mo = instantiate_bottom_node(model_mo, name_mo) // Add it to the type mapping dict_add(dict_read(model_mo, "type_mapping"), new_element_mo, type_mo) // Add all attribute types at this level Integer counter_mo Integer max_mo Element keys_mo keys_mo = dict_keys(attribute_types) counter_mo = 0 max_mo = list_len(keys_mo) Element attr_name_mo Element attr_type_mo Element created_attr_mo Element created_edge_mo Element metamodel_mo metamodel_mo = dict_read(dict_read(model_mo, "metamodel"), "model") // For all new attributes while (integer_lt(counter_mo, max_mo)): attr_name_mo = set_pop(keys_mo) attr_type_mo = dict_read(attribute_types, attr_name_mo) created_attr_mo = create_edge(new_element_mo, attr_type_mo) created_edge_mo = create_edge(created_attr_mo, attr_name_mo) // Add it to the model dict_add(dict_read(model_mo, "model"), string_join("__", cast_id2s(attr_name_mo)), attr_name_mo) dict_add(dict_read(model_mo, "model"), string_join("__", cast_id2s(attr_type_mo)), attr_type_mo) dict_add(dict_read(model_mo, "model"), string_join("__", cast_id2s(created_attr_mo)), created_attr_mo) dict_add(dict_read(model_mo, "model"), string_join("__", cast_id2s(created_edge_mo)), created_edge_mo) // And add the typing dict_add(dict_read(model_mo, "type_mapping"), attr_name_mo, dict_read(metamodel_mo, "__String")) dict_add(dict_read(model_mo, "type_mapping"), attr_type_mo, dict_read(metamodel_mo, "Type")) dict_add(dict_read(model_mo, "type_mapping"), created_attr_mo, dict_read(metamodel_mo, "Attribute")) dict_add(dict_read(model_mo, "type_mapping"), created_edge_mo, dict_read(metamodel_mo, "__Name")) // Increase while loop counter counter_mo = integer_addition(counter_mo, 1) // Similarly for instantiated attributes counter_mo = 0 keys_mo = dict_keys(attribute_instances) max_mo = list_len(keys_mo) Element attr_definer_class_mo Element attr_type_edge_mo Element attr_value_mo Element attr_edge_mo while (integer_lt(counter_mo, max_mo)): // Look it up attr_name_mo = set_pop(keys_mo) attr_value_mo = dict_read(attribute_instances, attr_name_mo) attr_definer_class_mo = find_attribute(type_mo, attr_name_mo, dict_read(dict_read(model_mo, "metamodel"), "type_mapping"), dict_read(model_mo, "inheritance")) attr_type_mo = dict_read(attr_definer_class_mo, attr_name_mo) attr_type_edge_mo = dict_read_edge(attr_definer_class_mo, attr_name_mo) attr_edge_mo = create_edge(new_element_mo, attr_value_mo) // Add to model dict_add(dict_read(model_mo, "model"), string_join("__", cast_id2s(attr_value_mo)), attr_value_mo) dict_add(dict_read(model_mo, "model"), string_join("__", cast_id2s(attr_edge_mo)), attr_edge_mo) // Type the new elements dict_add(dict_read(model_mo, "type_mapping"), attr_value_mo, attr_type_mo) dict_add(dict_read(model_mo, "type_mapping"), attr_edge_mo, attr_type_edge_mo) counter_mo = integer_addition(counter_mo, 1) return new_element_mo Element function instantiate_new_model(metamodel_inm : Element, inheritance_inm : Element): Element model_inm model_inm = create_node() dict_add(model_inm, "model", create_node()) dict_add(model_inm, "type_mapping", create_node()) dict_add(model_inm, "metamodel", metamodel_inm) dict_add(model_inm, "inheritance", inheritance_inm) return model_inm Element function generate_bottom_type_mapping(model_tm : Element): Element mm_tm mm_tm = dict_read(dict_read(model_tm, "metamodel"), "model") dict_delete(model_tm, "type_mapping") Element tm_tm tm_tm = create_node() dict_add(model_tm, "type_mapping", tm_tm) // Iterate over every element Element elem_keys_tm Element elem_tm elem_keys_tm = dict_keys(dict_read(model_tm, "model")) while (integer_lt(0, read_nr_out(elem_keys_tm))): elem_tm = dict_read(dict_read(model_tm, "model"), set_pop(elem_keys_tm)) if (is_edge(elem_tm)): dict_add(tm_tm, elem_tm, dict_read(mm_tm, "Edge")) else: if (string_neq(cast_v2s(elem_tm), "None")): dict_add(tm_tm, elem_tm, dict_read(mm_tm, cast_v2s(typeof(elem_tm)))) else: dict_add(tm_tm, elem_tm, dict_read(mm_tm, "Node")) return model_tm