Bläddra i källkod

Relaxed MvS constraint to allow for ambiguous keys (though not for duplicates!), thus solving the cardinality problem

Yentl Van Tendeloo 9 år sedan
förälder
incheckning
d8b0642b31

+ 4 - 15
bootstrap/conformance_scd.alc

@@ -13,6 +13,10 @@ Boolean function is_nominal_instance(model : Element, instance : Element, type :
 		// type is not even in the specified metamodel, so this will never work
 		return False
 
+	if (bool_not(dict_in_node(model["type_mapping"], instance))):
+		// Doesn't even have a type
+		return False
+
 	return is_nominal_subtype(model["metamodel"], dict_read_node(model["type_mapping"], instance), type)
 
 Boolean function is_nominal_subtype(metamodel : Element, subclass : Element, superclass : Element):
@@ -122,7 +126,6 @@ String function conformance_scd(model : Element):
 					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
@@ -164,52 +167,38 @@ String function conformance_scd(model : Element):
 
 			check_list = selectPossibleOutgoing(model, model_name, dict_keys(cardinalities))
 			while (0 < list_len(check_list)):
-				log("Check cardinalities for " + model_name)
 				check_type = set_pop(check_list)
 				if (dict_in(cardinalities, check_type)):
-					log("Target Got some cardinalities to check!")
 					// Cardinalities defined for this association, so check them
 					lower_val = cardinalities[check_type]["tlc"]
 					upper_val = cardinalities[check_type]["tuc"]
-					log("Read instances for " + cast_e2s(model_name))
-					log("  of " + cast_e2s(check_type))
 					instances = list_len(allOutgoingAssociationInstances(model, model_name, check_type))
-					log("Instances: " + cast_i2s(instances))
 					if (dict_in(cardinalities[check_type], "tlc")):
 						// A lower cardinality was defined at the target
-						log("TLC Compare with " + cast_i2s(instances))
 						if (integer_gt(cardinalities[check_type]["tlc"], instances)):
 							return "Lower cardinality violation for outgoing edge at " + model_name
 					if (dict_in(cardinalities[check_type], "tuc")):
 						// An upper cardinality was defined at the target
-						log("TUC Compare with " + cast_i2s(instances))
 						if (integer_gt(cardinalities[check_type]["tuc"], instances)):
 							return "Upper cardinality violation for outgoing edge at " + model_name
 
 			// Identical, but for outgoing, and thus for A in the figure
 			check_list = selectPossibleIncoming(model, model_name, dict_keys(cardinalities))
 			while (0 < list_len(check_list)):
-				log("Check cardinalities for " + model_name)
 				check_type = set_pop(check_list)
-				log(cast_e2s(check_type))
 				if (dict_in(cardinalities, check_type)):
-					log("Source Got some cardinalities to check!")
 					// 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))
-					log("Instances: " + cast_i2s(list_len(instances)))
 					if (dict_in(cardinalities[check_type], "slc")):
 						// A lower cardinality was defined at the source
-						log("SLC Compare with " + cast_i2s(instances))
 						if (integer_gt(cardinalities[check_type]["slc"], instances)):
 							return "Lower cardinality violation for incoming edge at " + model_name
 					if (dict_in(cardinalities[check_type], "suc")):
 						// An upper cardinality was defined at the source
-						log("SUC Compare with " + cast_i2s(instances))
 						if (integer_gt(cardinalities[check_type]["suc"], instances)):
 							return "Upper cardinality violation for incoming edge at " + model_name
-			log("Done for " + model_name)
 
 	// Check multiplicities, if they are defined (optional)
 	Element metamodel_keys

+ 9 - 7
bootstrap/object_operations.alc

@@ -81,9 +81,10 @@ Element function allOutgoingAssociationInstances(model : Element, source_name :
 	i = 0
 	while (i < nr_out):
 		out = read_out(model["model"][source_name], i)
-		out_name = reverseKeyLookup(model["model"], out)
-		if (is_nominal_instance(model, out, model["metamodel"]["model"][assoc_name])):
-			set_add(result, out_name)
+		if (set_in_node(model["model"], out)):
+			out_name = reverseKeyLookup(model["model"], out)
+			if (is_nominal_instance(model, out, model["metamodel"]["model"][assoc_name])):
+				set_add(result, out_name)
 		i = i + 1
 	return result
 
@@ -99,10 +100,11 @@ Element function allIncomingAssociationInstances(model : Element, target_name :
 	nr_in = read_nr_in(model["model"][target_name])
 	i = 0
 	while (i < nr_in):
-		in = read_out(model["model"][target_name], i)
-		in_name = reverseKeyLookup(model["model"], in)
-		if (is_nominal_instance(model, in, model["metamodel"]["model"][assoc_name])):
-			set_add(result, in_name)
+		in = read_in(model["model"][target_name], i)
+		if (set_in_node(model["model"], in)):
+			in_name = reverseKeyLookup(model["model"], in)
+			if (is_nominal_instance(model, in, model["metamodel"]["model"][assoc_name])):
+				set_add(result, in_name)
 		i = i + 1
 	return result
 

+ 1 - 1
kernel/modelverse_kernel/primitives.py

@@ -110,7 +110,7 @@ def float_neg(a, **remainder):
 
 def string_join(a, b, **remainder):
     a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result = yield [("CNV", [a_value + b_value])]
+    result = yield [("CNV", [str(a_value) + str(b_value)])]
     raise PrimitiveFinished(result)
 
 def string_split(a, b, **remainder):

+ 9 - 15
state/modelverse_state/main.py

@@ -243,14 +243,11 @@ class ModelverseState(object):
                 if v == value:
                     # Found a match
                     # Now get the target of the original link
-                    if len(data_links) > 1:
-                        return (None, status.FAIL_RDICTE_UNCERTAIN)
-                    else:
-                        if found is not None:
-                            print("Duplicate key on value: %s (%s <-> %s)!" % (v, found, e1))
-                            return (None, status.FAIL_RDICTE_AMBIGUOUS)
-                        found = e1
-                        self.cache.setdefault(node, {})[value] = e1
+                    if found is not None:
+                        print("Duplicate key on value: %s (%s <-> %s)!" % (v, found, e1))
+                        return (None, status.FAIL_RDICTE_AMBIGUOUS)
+                    found = e1
+                    self.cache.setdefault(node, {})[value] = e1
         if found is not None:
             return (found, status.SUCCESS)
         else:
@@ -282,13 +279,10 @@ class ModelverseState(object):
                 if target == value_node:
                     # Found a match
                     # Now get the target of the original link
-                    if len(data_links) > 1:
-                        return (None, status.FAIL_RDICTNE_UNCERTAIN)
-                    else:
-                        if found is not None:
-                            print("Duplicate key on node: %s (%s <-> %s)!" % (value_node, found, e1))
-                            return (None, status.FAIL_RDICTNE_AMBIGUOUS)
-                        found = e1
+                    if found is not None:
+                        print("Duplicate key on node: %s (%s <-> %s)!" % (value_node, found, e1))
+                        return (None, status.FAIL_RDICTNE_AMBIGUOUS)
+                    found = e1
         if found is not None:
             return (found, status.SUCCESS)
         else: