|
@@ -96,104 +96,106 @@ String function conformance_scd(model : Element):
|
|
|
cardinalities = create_node()
|
|
|
|
|
|
// Create dictionary with all associations and allowed cardinalities
|
|
|
- keys = dict_keys(metamodel["model"])
|
|
|
- Integer slc
|
|
|
- Integer suc
|
|
|
- Integer tlc
|
|
|
- Integer tuc
|
|
|
- String key
|
|
|
- Element tmp_dict
|
|
|
- while (0 < list_len(keys)):
|
|
|
- key = set_pop(keys)
|
|
|
- if (is_nominal_instance(metamodel, metamodel["model"][key], scd["model"]["Association"])):
|
|
|
- tmp_dict = create_node()
|
|
|
- slc = read_attribute(metamodel, key, "source_lower_cardinality")
|
|
|
- suc = read_attribute(metamodel, key, "source_upper_cardinality")
|
|
|
- tlc = read_attribute(metamodel, key, "target_lower_cardinality")
|
|
|
- tuc = read_attribute(metamodel, key, "target_upper_cardinality")
|
|
|
- if (element_neq(slc, read_root())):
|
|
|
- dict_add(tmp_dict, "slc", slc)
|
|
|
- if (element_neq(suc, read_root())):
|
|
|
- dict_add(tmp_dict, "suc", suc)
|
|
|
- if (element_neq(tlc, read_root())):
|
|
|
- dict_add(tmp_dict, "tlc", tlc)
|
|
|
- if (element_neq(tuc, read_root())):
|
|
|
- dict_add(tmp_dict, "tuc", tuc)
|
|
|
-
|
|
|
- if (list_len(tmp_dict) > 0):
|
|
|
- dict_add(cardinalities, key, tmp_dict)
|
|
|
-
|
|
|
- // Iterate over each element of the model, finding out whether everything is fine
|
|
|
- keys = dict_keys(model["model"])
|
|
|
- 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
|
|
|
-
|
|
|
- // Check cardinality for all of our edges
|
|
|
- //
|
|
|
- // SLC..SUC TLC..TUC
|
|
|
- // A ---------------------> B
|
|
|
- //
|
|
|
- // First the incoming, so we are at B in the above figure
|
|
|
- Integer lower_val
|
|
|
- Integer upper_val
|
|
|
- Integer instances
|
|
|
-
|
|
|
- check_list = selectPossibleIncoming(model, model_name, dict_keys(cardinalities))
|
|
|
- while (0 < list_len(check_list)):
|
|
|
- check_type = set_pop(check_list)
|
|
|
- if (dict_in(cardinalities, reverseKeyLookup(metamodel["model"], check_type))):
|
|
|
- // Cardinalities defined for this association, so check them
|
|
|
- lower_val = cardinalities[check_type]["tlc"]
|
|
|
- upper_val = cardinalities[check_type]["tlc"]
|
|
|
- instances = list_len(allIncomingAssociationInstances(model, element, check_type))
|
|
|
- if (dict_in(cardinalities[check_type], "tlc")):
|
|
|
- // A lower cardinality was defined at the target
|
|
|
- if (integer_gt(cardinalities[check_type]["tlc"], instances)):
|
|
|
- return "Lower cardinality violation for incoming edge at " + model_name
|
|
|
- if (dict_in(cardinalities[check_type], "tuc")):
|
|
|
- // An upper cardinality was defined at the target
|
|
|
- if (integer_gt(cardinalities[check_type]["tuc"], instances)):
|
|
|
- return "Upper cardinality violation for incoming edge at " + model_name
|
|
|
-
|
|
|
- // Identical, but for outgoing, and thus for A in the figure
|
|
|
- check_list = selectPossibleOutgoing(model, model_name, dict_keys(cardinalities))
|
|
|
- while (0 < list_len(check_list)):
|
|
|
- check_type = set_pop(check_list)
|
|
|
- if (dict_in(cardinalities, reverseKeyLookup(metamodel["model"], check_type))):
|
|
|
- // Cardinalities defined for this association, so check them
|
|
|
- lower_val = cardinalities[check_type]["slc"]
|
|
|
- upper_val = cardinalities[check_type]["slc"]
|
|
|
- instances = list_len(allOutgoingAssociationInstances(model, element, check_type))
|
|
|
- if (dict_in(cardinalities[check_type], "slc")):
|
|
|
- // A lower cardinality was defined at the source
|
|
|
- if (integer_gt(cardinalities[check_type]["slc"], instances)):
|
|
|
- return "Lower cardinality violation for outgoing edge at " + model_name
|
|
|
- if (dict_in(cardinalities[check_type], "suc")):
|
|
|
- // An upper cardinality was defined at the source
|
|
|
- if (integer_gt(cardinalities[check_type]["suc"], instances)):
|
|
|
- return "Upper cardinality violation for outgoing edge at " + model_name
|
|
|
+ if (list_len(model["model"]) > 0):
|
|
|
+ keys = dict_keys(metamodel["model"])
|
|
|
+ Integer slc
|
|
|
+ Integer suc
|
|
|
+ Integer tlc
|
|
|
+ Integer tuc
|
|
|
+ String key
|
|
|
+ Element tmp_dict
|
|
|
+ while (0 < list_len(keys)):
|
|
|
+ key = set_pop(keys)
|
|
|
+ if (is_nominal_instance(metamodel, metamodel["model"][key], scd["model"]["Association"])):
|
|
|
+ tmp_dict = create_node()
|
|
|
+ slc = read_attribute(metamodel, key, "source_lower_cardinality")
|
|
|
+ suc = read_attribute(metamodel, key, "source_upper_cardinality")
|
|
|
+ tlc = read_attribute(metamodel, key, "target_lower_cardinality")
|
|
|
+ tuc = read_attribute(metamodel, key, "target_upper_cardinality")
|
|
|
+ if (element_neq(slc, read_root())):
|
|
|
+ dict_add(tmp_dict, "slc", slc)
|
|
|
+ if (element_neq(suc, read_root())):
|
|
|
+ dict_add(tmp_dict, "suc", suc)
|
|
|
+ if (element_neq(tlc, read_root())):
|
|
|
+ dict_add(tmp_dict, "tlc", tlc)
|
|
|
+ if (element_neq(tuc, read_root())):
|
|
|
+ dict_add(tmp_dict, "tuc", tuc)
|
|
|
+
|
|
|
+ if (list_len(tmp_dict) > 0):
|
|
|
+ log("Found cardinalities for " + key)
|
|
|
+ dict_add(cardinalities, key, tmp_dict)
|
|
|
+
|
|
|
+ // Iterate over each element of the model, finding out whether everything is fine
|
|
|
+ keys = dict_keys(model["model"])
|
|
|
+ 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
|
|
|
+
|
|
|
+ // Check cardinality for all of our edges
|
|
|
+ //
|
|
|
+ // SLC..SUC TLC..TUC
|
|
|
+ // A ---------------------> B
|
|
|
+ //
|
|
|
+ // First the incoming, so we are at B in the above figure
|
|
|
+ Integer lower_val
|
|
|
+ Integer upper_val
|
|
|
+ Integer instances
|
|
|
+
|
|
|
+ check_list = selectPossibleIncoming(model, model_name, dict_keys(cardinalities))
|
|
|
+ while (0 < list_len(check_list)):
|
|
|
+ check_type = set_pop(check_list)
|
|
|
+ if (dict_in(cardinalities, reverseKeyLookup(metamodel["model"], check_type))):
|
|
|
+ // Cardinalities defined for this association, so check them
|
|
|
+ lower_val = cardinalities[check_type]["tlc"]
|
|
|
+ upper_val = cardinalities[check_type]["tuc"]
|
|
|
+ instances = list_len(allIncomingAssociationInstances(model, element, check_type))
|
|
|
+ if (dict_in(cardinalities[check_type], "tlc")):
|
|
|
+ // A lower cardinality was defined at the target
|
|
|
+ if (integer_gt(cardinalities[check_type]["tlc"], instances)):
|
|
|
+ return "Lower cardinality violation for incoming edge at " + model_name
|
|
|
+ if (dict_in(cardinalities[check_type], "tuc")):
|
|
|
+ // An upper cardinality was defined at the target
|
|
|
+ if (integer_gt(cardinalities[check_type]["tuc"], instances)):
|
|
|
+ return "Upper cardinality violation for incoming edge at " + model_name
|
|
|
+
|
|
|
+ // Identical, but for outgoing, and thus for A in the figure
|
|
|
+ check_list = selectPossibleOutgoing(model, model_name, dict_keys(cardinalities))
|
|
|
+ while (0 < list_len(check_list)):
|
|
|
+ check_type = set_pop(check_list)
|
|
|
+ if (dict_in(cardinalities, reverseKeyLookup(metamodel["model"], check_type))):
|
|
|
+ // Cardinalities defined for this association, so check them
|
|
|
+ lower_val = cardinalities[check_type]["slc"]
|
|
|
+ upper_val = cardinalities[check_type]["suc"]
|
|
|
+ instances = list_len(allOutgoingAssociationInstances(model, element, check_type))
|
|
|
+ if (dict_in(cardinalities[check_type], "slc")):
|
|
|
+ // A lower cardinality was defined at the source
|
|
|
+ if (integer_gt(cardinalities[check_type]["slc"], instances)):
|
|
|
+ return "Lower cardinality violation for outgoing edge at " + model_name
|
|
|
+ if (dict_in(cardinalities[check_type], "suc")):
|
|
|
+ // An upper cardinality was defined at the source
|
|
|
+ if (integer_gt(cardinalities[check_type]["suc"], instances)):
|
|
|
+ return "Upper cardinality violation for outgoing edge at " + model_name
|
|
|
|
|
|
// Check multiplicities, if they are defined (optional)
|
|
|
Element metamodel_keys
|