|
@@ -3,56 +3,29 @@ include "library.alh"
|
|
|
include "object_operations.alh"
|
|
|
include "constructors.alh"
|
|
|
|
|
|
-Element function set_copy(elem_to_copy : Element):
|
|
|
- Element result
|
|
|
- Integer i
|
|
|
- Integer max
|
|
|
-
|
|
|
- result = create_node()
|
|
|
-
|
|
|
- // Expand the provided list by including all elements that need to be checked
|
|
|
- i = 0
|
|
|
- max = read_nr_out(elem_to_copy)
|
|
|
- while (i < max):
|
|
|
- set_add(result, read_edge_dst(read_out(elem_to_copy, i)))
|
|
|
- i = i + 1
|
|
|
-
|
|
|
- return result
|
|
|
-
|
|
|
Boolean function is_direct_instance(model : Element, instance : Element, type : Element):
|
|
|
// Just check whether or not the type mapping specifies the type as the type of the instance
|
|
|
return element_eq(dict_read_node(model["type_mapping"], instance), type)
|
|
|
|
|
|
Boolean function is_nominal_instance(model : Element, instance : Element, type : Element):
|
|
|
- return is_nominal_subtype(type, dict_read_node(model["type_mapping"], instance), model["metamodel"]["type_mapping"], model["inheritance"])
|
|
|
-
|
|
|
-Boolean function is_nominal_subtype(superclass : Element, subclass : Element, types : Element, inheritance_link : Element):
|
|
|
- Integer counter
|
|
|
- Integer i
|
|
|
- Element edge
|
|
|
- Element destination
|
|
|
+ return is_nominal_subtype(model["metamodel"], dict_read_node(model["type_mapping"], instance), type)
|
|
|
|
|
|
- // End of recursion
|
|
|
- if (element_eq(superclass, subclass)):
|
|
|
+Boolean function is_nominal_subtype(metamodel : Element, subclass : Element, superclass : Element):
|
|
|
+ if (element_eq(subclass, superclass)):
|
|
|
return True
|
|
|
|
|
|
- // Iterate over all superclasses of the found class
|
|
|
- counter = read_nr_out(subclass)
|
|
|
- i = 0
|
|
|
- while (i < counter):
|
|
|
- edge = read_out(subclass, i)
|
|
|
- // Check if it even has a type (to prevent errors)
|
|
|
- if (dict_in_node(types, edge)):
|
|
|
- // Check whether it is an inheritance edge, as there is no other distinction between them
|
|
|
- if (element_eq(dict_read_node(types, edge), inheritance_link)):
|
|
|
- // It is an inheritance edge, so follow it to its destination
|
|
|
- destination = read_edge_dst(edge)
|
|
|
- // Found a new superclass to test
|
|
|
- if (is_nominal_subtype(superclass, destination, types, inheritance_link)):
|
|
|
- return True
|
|
|
- i = i + 1
|
|
|
+ Element superclasses
|
|
|
+ Element new_superclass
|
|
|
+ Element result
|
|
|
+
|
|
|
+ superclasses = get_superclasses(metamodel, subclass)
|
|
|
+
|
|
|
+ while (0 < list_len(superclasses)):
|
|
|
+ new_superclass = set_pop(superclasses)
|
|
|
+ result = is_nominal_subtype(metamodel, new_superclass, superclass)
|
|
|
+ if (result):
|
|
|
+ return True
|
|
|
|
|
|
- // No link seems to have been found, so it is False
|
|
|
return False
|
|
|
|
|
|
Boolean function is_structural_instance(model : Element, instance : Element, type : Element):
|
|
@@ -97,53 +70,51 @@ Boolean function is_structural_subtype(subtype : Element, supertype : Element):
|
|
|
|
|
|
String function conformance_scd(model : Element):
|
|
|
// Initialization
|
|
|
- Element work_node
|
|
|
- Element model_src
|
|
|
- Element metamodel_src
|
|
|
- Element model_dst
|
|
|
- Element metamodel_dst
|
|
|
- Element models
|
|
|
- Element metamodels
|
|
|
- models = set_copy(model["model"])
|
|
|
-
|
|
|
+ Element keys
|
|
|
+ Element metamodel
|
|
|
Element typing
|
|
|
+ String model_name
|
|
|
+ Element src_model
|
|
|
+ Element dst_model
|
|
|
+ Element src_metamodel
|
|
|
+ Element dst_metamodel
|
|
|
+ Element element
|
|
|
+
|
|
|
+ // Load in variables
|
|
|
+ keys = dict_keys(model["model"])
|
|
|
+ metamodel = model["metamodel"]
|
|
|
typing = model["type_mapping"]
|
|
|
- metamodels = set_copy(model["metamodel"]["model"])
|
|
|
- Element inheritance
|
|
|
- inheritance = model["metamodel"]["inheritance"]
|
|
|
- Element metamodel_typing
|
|
|
- metamodel_typing = 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 (dict_len(models) > 0):
|
|
|
- work_node = set_pop(models)
|
|
|
- // Basic check: does the element have a type
|
|
|
- if (bool_not(dict_in_node(typing, work_node))):
|
|
|
- return "Model has no type specified: " + getName(model, work_node)
|
|
|
-
|
|
|
- // Basic check: is the type of the element part of the metamodel
|
|
|
- if (bool_not(set_in_node(metamodels, dict_read_node(typing, work_node)))):
|
|
|
- return "Type of element not in specified metamodel: " + getName(model, work_node)
|
|
|
-
|
|
|
- // For edges only: check whether the source is typed according to the metamodel
|
|
|
- if (is_edge(work_node)):
|
|
|
- model_src = read_edge_src(work_node)
|
|
|
- metamodel_src = read_edge_src(dict_read_node(typing, work_node))
|
|
|
- log((getName(model, model_src) + " : ") + getName(model["metamodel"], metamodel_src))
|
|
|
- if (bool_not(is_nominal_instance(model, model_src, metamodel_src))):
|
|
|
- return "Source of model edge not typed by source of type: " + getName(model, work_node)
|
|
|
-
|
|
|
- // For edges only: check whether the destination is typed according to the metamodel
|
|
|
- if (is_edge(work_node)):
|
|
|
- model_dst = read_edge_dst(work_node)
|
|
|
- metamodel_dst = read_edge_dst(dict_read_node(typing, work_node))
|
|
|
- if (bool_not(is_nominal_instance(model, model_dst, metamodel_dst))):
|
|
|
- return "Destination of model edge not typed by destination of type: " + getName(model, work_node)
|
|
|
+
|
|
|
+ // Iterate over each element of the model, finding out whether everything is fine
|
|
|
+ while (0 < list_len(keys)):
|
|
|
+ model_name = set_pop(keys)
|
|
|
+ element = model["model"][model_name]
|
|
|
+
|
|
|
+ if (bool_not(dict_in_node(typing, element))):
|
|
|
+ return "Model has no type specified: " + model_name
|
|
|
+
|
|
|
+ if (bool_not(set_in_node(metamodel["model"], dict_read_node(typing, element)))):
|
|
|
+ return "Type of element not in specified metamodel: " + model_name
|
|
|
+
|
|
|
+ if (bool_not(is_nominal_instance(model, element, dict_read_node(typing, element)))):
|
|
|
+ return "Element is not an instance of its specified type: " + model_name
|
|
|
+
|
|
|
+ if (is_edge(element)):
|
|
|
+ src_model = read_edge_src(element)
|
|
|
+ dst_model = read_edge_dst(element)
|
|
|
+ src_metamodel = read_edge_src(dict_read_node(typing, element))
|
|
|
+ dst_metamodel = read_edge_dst(dict_read_node(typing, element))
|
|
|
+
|
|
|
+ if (bool_not(is_nominal_instance(model, src_model, src_metamodel))):
|
|
|
+ return "Source of model edge not typed by source of type: " + model_name
|
|
|
+
|
|
|
+ if (bool_not(is_nominal_instance(model, dst_model, dst_metamodel))):
|
|
|
+ return "Destination of model edge not typed by source of type: " + model_name
|
|
|
|
|
|
// Structure seems fine, now do static semantics
|
|
|
- if (dict_in(model["metamodel"], "constraints")):
|
|
|
+ if (dict_in(metamodel, "constraints")):
|
|
|
Element constraint_function
|
|
|
- constraint_function = model["metamodel"]["constraints"]
|
|
|
+ constraint_function = metamodel["constraints"]
|
|
|
return constraint_function(model)
|
|
|
else:
|
|
|
return "OK"
|