|
@@ -13,6 +13,10 @@ Boolean function is_nominal_instance(model : Element, instance : String, type :
|
|
|
// type is not even in the specified metamodel, so this will never work
|
|
|
return False
|
|
|
|
|
|
+ if (bool_and(is_edge(model["metamodel"]["model"][type]), bool_not(is_edge(model["model"][instance])))):
|
|
|
+ // type is an edge, but we aren't
|
|
|
+ return False
|
|
|
+
|
|
|
if (bool_not(dict_in_node(model["type_mapping"], model["model"][instance]))):
|
|
|
// Doesn't even have a type
|
|
|
return False
|
|
@@ -57,8 +61,7 @@ String function conformance_scd(model : Element):
|
|
|
String check_type
|
|
|
Element cardinalities
|
|
|
Element scd
|
|
|
- String error_msg
|
|
|
- error_msg = ""
|
|
|
+ Integer instances
|
|
|
|
|
|
// Load in variables
|
|
|
scd = import_node("models/SimpleClassDiagrams")
|
|
@@ -76,6 +79,7 @@ String function conformance_scd(model : Element):
|
|
|
String key
|
|
|
Element tmp_dict
|
|
|
|
|
|
+ log("Start attribute read")
|
|
|
while (0 < list_len(keys)):
|
|
|
key = set_pop(keys)
|
|
|
if (is_nominal_instance(metamodel, key, "Association")):
|
|
@@ -96,31 +100,39 @@ String function conformance_scd(model : Element):
|
|
|
|
|
|
if (list_len(tmp_dict) > 0):
|
|
|
dict_add(cardinalities, key, tmp_dict)
|
|
|
+ log("Finish attribute read")
|
|
|
|
|
|
// 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)
|
|
|
+ log("Check " + model_name)
|
|
|
element = model["model"][model_name]
|
|
|
|
|
|
+ log("1")
|
|
|
if (bool_not(dict_in_node(typing, element))):
|
|
|
return "Model has no type specified: " + model_name
|
|
|
|
|
|
+ log("2")
|
|
|
if (bool_not(set_in_node(metamodel["model"], dict_read_node(typing, element)))):
|
|
|
return "Type of element not in specified metamodel: " + model_name
|
|
|
|
|
|
+ log("3")
|
|
|
if (bool_not(is_nominal_instance(model, model_name, reverseKeyLookup(metamodel["model"], dict_read_node(typing, element))))):
|
|
|
return "Element is not an instance of its specified type: " + model_name
|
|
|
|
|
|
+ log("4")
|
|
|
if (is_edge(element)):
|
|
|
src_model = reverseKeyLookup(model["model"], read_edge_src(element))
|
|
|
dst_model = reverseKeyLookup(model["model"], read_edge_dst(element))
|
|
|
src_metamodel = reverseKeyLookup(metamodel["model"], read_edge_src(dict_read_node(typing, element)))
|
|
|
dst_metamodel = reverseKeyLookup(metamodel["model"], read_edge_dst(dict_read_node(typing, element)))
|
|
|
|
|
|
+ log("5")
|
|
|
if (bool_not(is_nominal_instance(model, src_model, src_metamodel))):
|
|
|
return "Source of model edge not typed by source of type: " + model_name
|
|
|
|
|
|
+ log("6")
|
|
|
if (bool_not(is_nominal_instance(model, dst_model, dst_metamodel))):
|
|
|
return "Destination of model edge not typed by source of type: " + model_name
|
|
|
|
|
@@ -130,17 +142,12 @@ String function conformance_scd(model : Element):
|
|
|
// A ---------------------> B
|
|
|
//
|
|
|
// First the incoming, so we are at B in the above figure
|
|
|
- Integer lower_val
|
|
|
- Integer upper_val
|
|
|
- Integer instances
|
|
|
-
|
|
|
+ log("7")
|
|
|
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, 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(allOutgoingAssociationInstances(model, model_name, check_type))
|
|
|
if (dict_in(cardinalities[check_type], "tlc")):
|
|
|
// A lower cardinality was defined at the target
|
|
@@ -152,13 +159,13 @@ String function conformance_scd(model : Element):
|
|
|
return "Upper cardinality violation for outgoing edge at " + model_name
|
|
|
|
|
|
// Identical, but for outgoing, and thus for A in the figure
|
|
|
+ log("8")
|
|
|
check_list = selectPossibleIncoming(model, model_name, dict_keys(cardinalities))
|
|
|
while (0 < list_len(check_list)):
|
|
|
+ log("LOOP")
|
|
|
check_type = set_pop(check_list)
|
|
|
if (dict_in(cardinalities, 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(allIncomingAssociationInstances(model, model_name, check_type))
|
|
|
if (dict_in(cardinalities[check_type], "slc")):
|
|
|
// A lower cardinality was defined at the source
|
|
@@ -169,16 +176,16 @@ String function conformance_scd(model : Element):
|
|
|
if (integer_lt(cardinalities[check_type]["suc"], instances)):
|
|
|
return "Upper cardinality violation for incoming edge at " + model_name
|
|
|
|
|
|
+ log("10")
|
|
|
Element constraint_function
|
|
|
- constraint_function = read_attribute(model["metamodel"], reverseKeyLookup(model["metamodel"]["model"], dict_read_node(model["type_mapping"], element)), "constraint")
|
|
|
+ constraint_function = read_attribute(metamodel, reverseKeyLookup(metamodel["model"], dict_read_node(typing, element)), "constraint")
|
|
|
if (element_neq(constraint_function, read_root())):
|
|
|
String result
|
|
|
- log("Calling constraint function!")
|
|
|
result = constraint_function(model, model_name)
|
|
|
- log("Done: result " + result)
|
|
|
if (result != "OK"):
|
|
|
return result
|
|
|
|
|
|
+ log("Start multiplicities")
|
|
|
// Check multiplicities, if they are defined (optional)
|
|
|
Element metamodel_keys
|
|
|
String metamodel_element
|
|
@@ -201,6 +208,7 @@ String function conformance_scd(model : Element):
|
|
|
// We have defined a lower cardinality, so check number of instances!
|
|
|
if (attr_value < list_len(allInstances(model, metamodel_element))):
|
|
|
return "Upper cardinality violated for class: " + metamodel_element
|
|
|
+ log("Finished multiplicities")
|
|
|
|
|
|
// Structure seems fine, now do static semantics
|
|
|
if (dict_in(metamodel, "constraints")):
|